如何设置 Gtk# TreeModelFilter 来过滤底层 TreeStore?
我已阅读 "GtkSharp TreeView 教程",其中作者描述了如何设置和使用 TreeModelFilter对于底层 ListStore(在教程“过滤数据”部分下)。该技术似乎不适用于底层分层 TreeStore。我想过滤多级 TreeStore 并在 TreeView 中显示结果。这让我很难过。有任何教程、示例或建议吗?
以下是代码。它与教程的代码基本相同,除了处理 TreeStore 而不是 ListStore 的构造和填充的更改之外。 {TreeStore 用于保存联系人的“姓名”和“电子邮件地址”,分为(并保存为)根“朋友”和“亲戚”的子级}
// compilation requires references to:
// gtk-sharp, atk-sharp and glib-sharp
using System;
using Gtk;
public class TreeViewExample
{
public static void Main()
{
Gtk.Application.Init();
new TreeViewExample();
Gtk.Application.Run();
}
Gtk.Entry filterEntry;
Gtk.TreeModelFilter filter;
public TreeViewExample()
{
// Create a Window
Gtk.Window window = new Gtk.Window("TreeView Example");
window.SetSizeRequest(500, 200);
window.DeleteEvent += delegate { Application.Quit(); };
// Create an Entry used to filter the tree
filterEntry = new Gtk.Entry();
// Fire off an event when the text in the Entry changes
filterEntry.Changed += OnFilterEntryTextChanged;
// Create a nice label describing the Entry
Gtk.Label filterLabel = new Gtk.Label("Search:");
// Put them both into a little box so they show up side by side
Gtk.HBox filterBox = new Gtk.HBox();
filterBox.PackStart(filterLabel, false, false, 5);
filterBox.PackStart(filterEntry, true, true, 5);
// Create our TreeView
Gtk.TreeView tv = new Gtk.TreeView();
// Create a box to hold the Entry and Tree
Gtk.VBox box = new Gtk.VBox();
// Add the widgets to the box
box.PackStart(filterBox, false, false, 5);
box.PackStart(tv, true, true, 5);
window.Add(box);
//setting up columns and renderers
Gtk.TreeViewColumn nameColumn = new Gtk.TreeViewColumn { Title = "Name" };
Gtk.CellRendererText nameCell = new Gtk.CellRendererText();
nameColumn.PackStart(nameCell, true);
Gtk.TreeViewColumn emailColumn = new Gtk.TreeViewColumn { Title = "Email" };
Gtk.CellRendererText emailCell = new Gtk.CellRendererText();
emailColumn.PackStart(emailCell, true);
// Add the columns to the TreeView
tv.AppendColumn(nameColumn);
tv.AppendColumn(emailColumn);
// Tell the Cell Renderers which items in the model to display
nameColumn.AddAttribute(nameCell, "text", 0);
emailColumn.AddAttribute(emailCell, "text", 1);
// Create a model that will hold two strings
Gtk.TreeStore contacts = new Gtk.TreeStore(typeof(string), typeof(string));
// Add some hierarchical data
Gtk.TreeIter treeiter;
//first root
treeiter = contacts.AppendValues("FRIENDS");
// 2 children of first root
contacts.AppendValues(treeiter, "Ogre", "[email protected]");
contacts.AppendValues(treeiter, "Bee", "[email protected]");
// second root
treeiter = contacts.AppendValues("RELATIVES");
// 3 children of second root
contacts.AppendValues(treeiter, "Mommy", "[email protected]");
contacts.AppendValues(treeiter, "Daddy", "[email protected]");
contacts.AppendValues(treeiter, "tom", "[email protected]");
filter = new Gtk.TreeModelFilter(contacts, null);
// Specify the function that determines which rows to filter out and which ones to display
filter.VisibleFunc = new Gtk.TreeModelFilterVisibleFunc(FilterTree);
// Assign the filter as our treeview's model
tv.Model = filter;
// Show the window and everything on it
window.ShowAll();
}
private void OnFilterEntryTextChanged(object o, System.EventArgs args)
{
// Since the filter text changed, tell the filter to re-determine which rows to display
filter.Refilter();
}
private bool FilterTree(Gtk.TreeModel model, Gtk.TreeIter iter)
{
string contactname = model.GetValue(iter, 0).ToString();
if (filterEntry.Text == "")
return true;
if (contactname.IndexOf(filterEntry.Text) > -1)
return true;
else
return false;
}
}
[我正在使用 mono 2.6.4 /monodevelop 2.4 / gtk -windows vista 上的锐利 2.12。]
I have read the "GtkSharp TreeView tutorial" wherein the author describes how to setup and use a TreeModelFilter for an underlying ListStore ( under the tutorial section "Filtering Data"). The technique doesn't seem to work for an underlying hierarchical TreeStore. I want to filter a multilevel TreeStore and show the results in a TreeView. Its giving me a real hard time. Are there any tutorials, samples, or suggestions for doing it ?
Following is the code. Its basically the same code as the tutorial except for changes to deal with construction and population of a TreeStore rather than a ListStore.
{The TreeStore is used to save "names" and "email addresses" of contacts , divided into (and saved as) children of the roots "friends" and "relatives" }
// compilation requires references to:
// gtk-sharp, atk-sharp and glib-sharp
using System;
using Gtk;
public class TreeViewExample
{
public static void Main()
{
Gtk.Application.Init();
new TreeViewExample();
Gtk.Application.Run();
}
Gtk.Entry filterEntry;
Gtk.TreeModelFilter filter;
public TreeViewExample()
{
// Create a Window
Gtk.Window window = new Gtk.Window("TreeView Example");
window.SetSizeRequest(500, 200);
window.DeleteEvent += delegate { Application.Quit(); };
// Create an Entry used to filter the tree
filterEntry = new Gtk.Entry();
// Fire off an event when the text in the Entry changes
filterEntry.Changed += OnFilterEntryTextChanged;
// Create a nice label describing the Entry
Gtk.Label filterLabel = new Gtk.Label("Search:");
// Put them both into a little box so they show up side by side
Gtk.HBox filterBox = new Gtk.HBox();
filterBox.PackStart(filterLabel, false, false, 5);
filterBox.PackStart(filterEntry, true, true, 5);
// Create our TreeView
Gtk.TreeView tv = new Gtk.TreeView();
// Create a box to hold the Entry and Tree
Gtk.VBox box = new Gtk.VBox();
// Add the widgets to the box
box.PackStart(filterBox, false, false, 5);
box.PackStart(tv, true, true, 5);
window.Add(box);
//setting up columns and renderers
Gtk.TreeViewColumn nameColumn = new Gtk.TreeViewColumn { Title = "Name" };
Gtk.CellRendererText nameCell = new Gtk.CellRendererText();
nameColumn.PackStart(nameCell, true);
Gtk.TreeViewColumn emailColumn = new Gtk.TreeViewColumn { Title = "Email" };
Gtk.CellRendererText emailCell = new Gtk.CellRendererText();
emailColumn.PackStart(emailCell, true);
// Add the columns to the TreeView
tv.AppendColumn(nameColumn);
tv.AppendColumn(emailColumn);
// Tell the Cell Renderers which items in the model to display
nameColumn.AddAttribute(nameCell, "text", 0);
emailColumn.AddAttribute(emailCell, "text", 1);
// Create a model that will hold two strings
Gtk.TreeStore contacts = new Gtk.TreeStore(typeof(string), typeof(string));
// Add some hierarchical data
Gtk.TreeIter treeiter;
//first root
treeiter = contacts.AppendValues("FRIENDS");
// 2 children of first root
contacts.AppendValues(treeiter, "Ogre", "[email protected]");
contacts.AppendValues(treeiter, "Bee", "[email protected]");
// second root
treeiter = contacts.AppendValues("RELATIVES");
// 3 children of second root
contacts.AppendValues(treeiter, "Mommy", "[email protected]");
contacts.AppendValues(treeiter, "Daddy", "[email protected]");
contacts.AppendValues(treeiter, "tom", "[email protected]");
filter = new Gtk.TreeModelFilter(contacts, null);
// Specify the function that determines which rows to filter out and which ones to display
filter.VisibleFunc = new Gtk.TreeModelFilterVisibleFunc(FilterTree);
// Assign the filter as our treeview's model
tv.Model = filter;
// Show the window and everything on it
window.ShowAll();
}
private void OnFilterEntryTextChanged(object o, System.EventArgs args)
{
// Since the filter text changed, tell the filter to re-determine which rows to display
filter.Refilter();
}
private bool FilterTree(Gtk.TreeModel model, Gtk.TreeIter iter)
{
string contactname = model.GetValue(iter, 0).ToString();
if (filterEntry.Text == "")
return true;
if (contactname.IndexOf(filterEntry.Text) > -1)
return true;
else
return false;
}
}
[I am using mono 2.6.4 /monodevelop 2.4 / gtk-sharp 2.12 on windows vista.]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
似乎在过滤树模型中的行时,只有当行的所有父行也可见时,该行才可见。由于您的过滤函数隐藏了父节点,因此即使文本匹配,它也不会显示子节点。我修改了您的代码来说明这个问题:
现在,父节点之一以“test”开头。如果您输入“test”,您将看到过滤工作正常。
当前结构的最
简单的解决方案是让过滤器函数根据模型中隐藏列中的值始终为“容器”节点(朋友和亲戚)返回 TRUE。它看起来不会完全像你想要的那样,但它会起作用。
GTK+ Treeview 教程虽然已经有一段时间没有更新了,但仍然是一个非常有用的资源满足您所有的 TreeView 需求。代码和示例都是 C 语言,但大部分仍然适用于 GTK#。
It seems that when filtering rows in a tree model, a row is only visible if ALL its parents are visible too. Since your filter function hides the parent nodes, it will not display the child nodes even if the text matches. I have modified your code to illustrate this problem:
Now, one of the parent nodes begins with 'test'. If you type 'test' you'll see the filtering works correctly.
}
The easiest solution with your current structure would be having the filter function always return TRUE for the 'container' nodes (Friends and Relatives), based upon a value in a hidden column in the model. It will not look exactly look the way you want, but it will work.
The GTK+ Treeview Tutorial, though not updated for some time,is still a VERY useful resource for all your TreeView needs. The code and examples are in C, but most of it still applies to GTK#.
为了达到代码的正确功能,我建议您按以下方式修改它:
1.向您的类添加新字段
private filterBool = false;
2.修改您的
FilterTree 方法到此状态:
3.添加缺少的方法
通过此修改,将检查每个节点是否有可能满足过滤条件的子节点。如果检测到任何节点,则不会丢弃该节点。
In order to reach correct functionality of your code, I suggest you to modify it in following manner:
1.Add new field
private filterBool = false;
to your class2.Modify your
FilterTree
method to this state:3.Add missing method
With this modification every node is checked for possible child nodes, which might fulfill filtering conditions. If any is detected, the node is not discarded.
Tinki 版本运行完美。我唯一不喜欢的是私有变量。这可以通过使用 InvestigateChildrenNodes 函数中的返回值来消除。
Tinki version works flawlessly. The only thing which I do not like is the private variable. This can be eliminated by using a return value in the InvestigateChildrenNodes function.