在GTK#延迟加载列表视图 [英] Lazy loaded list view in GTK#

查看:238
本文介绍了在GTK#延迟加载列表视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我期待通过在GTK#列表视图中显示大数据集,性能是一个问题在这里。我目前使用带有ListStore支持一个TreeView,但加入我的所有数据到ListStore需要永远。是否有一些在GTK支持数据的延迟加载列表视图控件?在的WinForms,你可以使用的DataGridView来处理这个的VirtualMode属性,但我没有看到的排序为GTK的东西。

I'm looking to display a large dataset via a list view in GTK# and performance is an issue here. I'm currently using a TreeView backed with a ListStore, but adding all my data to the ListStore takes forever. Is there a list view widget of some sort in GTK that supports lazy loading of data? In Winforms, you can use the VirtualMode property of DataGridView to handle this, but I don't see anything of the sort for GTK.

推荐答案

有,据我所知,没有任何部件做你想要用GTK,但是,你可以做类似的事情,在最终的结果是什么,要VirtualMode属性,在TreeView。

There, as far as I am aware, no widget to do what you want in Gtk, however, you can do something similar, in the end result, to the VirtualMode property, in the TreeView.

与TreeView控件的问题是,从它的模式提前将取回的所有数据。如果没有这个,那么我建议一个模型仅仅处理这个问题,但不幸的是,TreeView的是贪婪的,当涉及到获取数据,从而进行控制时,从需要的视图的数据加载,否则这是怎么回事去到能够告诉当行是可见的,所以通知模型,或代理为行获取的数据,因为它变得可见。

The problem with The TreeView control is that it will fetch all data from it's model in advance. If it were not for this then I would suggest a model only approach to this problem, but unfortunately the TreeView is greedy when it comes to fetching the data, so controlling when data is loaded from the view is needed, else how else is it going to be able to tell when a row is visible and thus inform the model, or a proxy to fetch the data for the row as it becomes visible.

您需要三件事得到这个工作。

You need 3 things to get this to work

1)模型在TreeView,最初拥有的所有行使用,但在任何领域的任何数据

2)无论您使用的数据库
获取数据的方法
3)确定哪些行来获取用于
数据的一个装置

1) a model to use in the treeview, which initially has all the rows but no data in any of the fields
2) a way of fetching the data from whatever database you use
3) a means of determining which rows to fetch data for

中的前两项可以在模型级进行。确定哪些行来获取需要的树形部件和确定正被显示的内容的行的方法。下面我使用的方法是不是最佳的,但它的工作,并且可以收拾和/或适合你心里有什么用。

The first two items can be done on the model level. Determining what rows to fetch needs the Treeview widget and a way of determining what rows are being displayed. The method I use below is not optimal, but it does work, and can be tidied up and/or adapted for whatever use you have in mind.

我使用的代理类被存储在模型和用于取特定于该行的数据。在我的例子它被称为ProxyClass。它获取并保持数据的行,这是最初为null。在这种情况下,提取方法只创建并返回一个字符串一些数据+ ID

I am using a proxy class to be stored in the model and is used to fetch data specific to that row. In my example it is called ProxyClass. It fetches and holds the data for a row, which is initially null. In this case the Fetch method just creates and returns a string "some data " + id

这将举行MYNODE的实例,从树节点,再$ P $继承psenting数据的行内。第一列返回在代理和第二列,这是从未示出保持的数据,保存代理类实例

This would be held inside a instance of MyNode, which inherits from TreeNode, representing a row of data. the first column returns the data held in the proxy and the second column, which is never shown, holds the proxy class instance.

您再创建NodeStore,你的模式,与MYNODE(ID)的实例填充它,你可以在下面的例子看到。

You then create your NodeStore, your model, populating it with instances of MyNode(id) as you can see below in the example.

当数据被装载在该控制是从CellDataFunc控制。这种方法的关键在于获得这个工作。该CellDataFunc负责设置在CellRendererText的文本通过传递给它的迭代器标识的行中的特定列。它被称为每次树状透着行,只为新发现的行时间。因此,将只适用于在显示屏上呈现的细胞获取数据。这给你当数据获取控制,从而获取它,只有当你需要它的手段。

The control over when data is loaded is controlled from CellDataFunc. This method is the key to getting this to work. The CellDataFunc is responsible for setting the text in the CellRendererText for a specific column in a row identified by the iterator passed to it. It is called every time the treeview reveals a row and for the newly revealed row only. Thus will only fetch data for cells that are rendered in the display. This gives you a means of controlling when the data is fetched, thus fetching it only when you need it.

您可以在TreeView使用CellDataFunc根据需要通过将其应用到与TreeViewColumn.SetCellDataFunc的一列装载数据。你只需要做到这一点的一列,因为它可以为整个行获取的数据。

You can make the TreeView use the CellDataFunc to load your data as needed by applying it to one of the columns with TreeViewColumn.SetCellDataFunc. You only need to do this on one column, as it can fetch the data for the entire row.

要停止所有但可见的列从具有它的数据取出,可以通过检查是否当前小区是在可见光范围内或不进行。要做到这一点,你叫TreeView.GetVisibleRange(出开始,OUT端),然后看是否传递给这个函数当前迭代器的开始和结束的范围,这是TreePath的对象之内,所以他们需要首先变成TreeIters。 Model.GetIter(出iter_start,启动)。然后检查是否iter.UserData.ToInt32()> = iter_start.UserData.ToInt32()和小于iter_end。如果从iter_start到iter_end则范围目前ITER瀑布取数据,否则离开它是。

To stop all but the visible rows from having it's data fetched, can be done by checking to see if the current cell is in the visible range or not. To do this you call TreeView.GetVisibleRange(out start,out end) then see if the current iterator passed to this function is within the start and end range , which are TreePath objects, so they need to be changed into TreeIters first. Model.GetIter(out iter_start, start). Then check to see if iter.UserData.ToInt32() >= iter_start.UserData.ToInt32() and less than iter_end. If the current iter falls in the range from iter_start to iter_end then fetch the data, else leave it be.

下面是我的榜样。

该ProxyClass

The ProxyClass

namespace LazyTree
{

    public class ProxyClass 
    {
      int id;
      string data;

      public ProxyClass (int id)
      {
        this.id = id;
        data = null;
      }


      public void Fetch()
      {
        data = "some data " + id;
      }


      public int Id
      {
        get { return id; }
      }

      public string Data
      {
        get {return data;}
      }
  }
}

自定义树节点实例

The custom TreeNode instance

namespace LazyTree
{
    [Gtk.TreeNode (ListOnly=true)]
    public class MyNode : Gtk.TreeNode
    {
        protected ProxyClass proxy;

        public MyNode (int id)
        {
            proxy = new ProxyClass(id);
        }

        [Gtk.TreeNodeValue (Column=1)]
        public ProxyClass Proxy
        {
            get {return proxy;}
        }

        [Gtk.TreeNodeValue (Column=0)]
        public string Data
        {
            get { return proxy.Data; }
        }
    }
}

,其中包括滚动窗口,和TreeView的窗口。这也是其中CellDataFunc定义,尽管可以在任何地方放

The window which includes the scrolled window, and treeview. This is also where the CellDataFunc is defined, although that could be put anywhere.

namespace LazyTree
{

    public class MyWindow : Gtk.Window
    {
        int NUMBER_COLUMNS = 10000;
        Gtk.NodeStore store;
        Gtk.NodeStore Store {
            get {
                if (store == null) {
                    store = new Gtk.NodeStore (typeof (MyNode));
                    for(int i = 0; i < NUMBER_COLUMNS; i++)
                    {
                        store.AddNode (new MyNode (i));
                    }
                }
                return store;
            }
        }


        protected void CellDataFunc(Gtk.TreeViewColumn column,
                                    Gtk.CellRenderer cell,
                                    Gtk.TreeModel model,
                                    Gtk.TreeIter iter)
        {
            try {
                string data = (string)model.GetValue(iter, 0);
                ProxyClass proxy = (ProxyClass)model.GetValue(iter, 1);
                Gtk.TreeView view = (Gtk.TreeView)column.TreeView;
                Gtk.TreePath start, end;
                bool go = view.GetVisibleRange(out start,out end);
                Gtk.TreeIter iter_start, iter_end;
                if(go)
                {
                    model.GetIter(out iter_start, start);
                    model.GetIter(out iter_end, end);
                }
                if (go &&
                    data == null && 
                    iter.UserData.ToInt32() >= iter_start.UserData.ToInt32() &&
                    iter.UserData.ToInt32() <= iter_end.UserData.ToInt32())
                {
                    Console.WriteLine("Lazy Loading " + proxy.Id + ", Visible: " + cell.Visible);
                    proxy.Fetch();
                }

                ((Gtk.CellRendererText)cell).Text = data;
            } catch(Exception e) {
                Console.WriteLine("error: " + e);
            }
        }


        public MyWindow () : base("Lazy Tree")
        {
            Gtk.NodeView view = new Gtk.NodeView(Store);

            Gtk.ScrolledWindow scroll = new Gtk.ScrolledWindow();
            scroll.Add(view);
            Add(scroll);
            Gtk.CellRendererText cell = new Gtk.CellRendererText ();
            view.AppendColumn ("Lazy Data", cell, "text", 0);

            Gtk.TreeViewColumn column = view.GetColumn(0);

            column.SetCellDataFunc(cell, CellDataFunc);
        }


        protected override bool OnDeleteEvent (Gdk.Event ev)
        {
            Gtk.Application.Quit ();
            return true;
        }

        public static void Main()
        {
            Gtk.Application.Init ();
                MyWindow win = new  MyWindow();
            win.SetDefaultSize(200, 200);
                    win.ShowAll ();
            Gtk.Application.Run ();
        }
    }


}

希望这是你以后有什么。

Hope that is what your after.

对于各有什么方法更好的解释看到C文件,及其参数做。 Mono的文档离开了很多有待改进。

See the c documentation for a better explanation of what each of the methods, and their parameters do. The Mono docs leave a lot to be desired.

SetCellDataFunc(C文档)
<一href=\"http://developer.gnome.org/gtk/stable/GtkTreeViewColumn.html#gtk-tree-view-column-set-cell-data-func\">http://developer.gnome.org/gtk/stable/GtkTreeViewColumn.html#gtk-tree-view-column-set-cell-data-func

SetCellDataFunc (C docs) http://developer.gnome.org/gtk/stable/GtkTreeViewColumn.html#gtk-tree-view-column-set-cell-data-func

(CeCellDataFunc)
<一href=\"http://developer.gnome.org/gtk/stable/GtkTreeViewColumn.html#GtkTreeCellDataFunc\">http://developer.gnome.org/gtk/stable/GtkTreeViewColumn.html#GtkTreeCellDataFunc

(CeCellDataFunc) http://developer.gnome.org/gtk/stable/GtkTreeViewColumn.html#GtkTreeCellDataFunc

(DestroyFunc)
<一href=\"http://developer.gnome.org/glib/unstable/glib-Datasets.html#GDestroyNotify\">http://developer.gnome.org/glib/unstable/glib-Datasets.html#GDestroyNotify

(DestroyFunc) http://developer.gnome.org/glib/unstable/glib-Datasets.html#GDestroyNotify

这篇关于在GTK#延迟加载列表视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆