简体   繁体   English

GTK#中的自定义树单元渲染器-如何获取单元数据?

[英]Custom tree cell renderers in GTK# - How to get cell data?

I'm using a TreeView in GTK# and now I need to use a custom cell renderer. 我在GTK#中使用TreeView,现在需要使用自定义单元格渲染器。

Although I got almost everything to work, there's one missing piece: The cell renderer must know what to render. 尽管我几乎可以完成所有工作,但是缺少一件:单元渲染器必须知道要渲染什么。

The data to render is a custom class. 要呈现的数据是一个自定义类。 I want to retrieve a field from that class. 我想从该类中检索一个字段。

Here's what I have so far 这是我到目前为止的

public class TreeItemCellRenderer : CellRenderer
{
    public override void GetSize (Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height)
    {
        base.GetSize (widget, ref cell_area, out x_offset, out y_offset, out width, out height);

        height = 16;
    }

    protected override void Render (Gdk.Drawable window,
        Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
    {
        base.Render (window, widget, background_area, cell_area, expose_area, flags);

        using (var layout = new Pango.Layout(widget.PangoContext)) {
            layout.Alignment = Pango.Alignment.Left;
            layout.SetText("Hello, World!");

            StateType state = flags.HasFlag(CellRendererState.Selected) ?
                widget.IsFocus ? StateType.Selected : StateType.Active : StateType.Normal;

            window.DrawLayout(widget.Style.TextGC(state), cell_area.X, cell_area.Y, layout);
        }
    }
}

Now I want to draw my custom field instead of "Hello, World!". 现在,我要绘制我的自定义字段,而不是“ Hello,World!”。 Some googling suggested SetProperty / GetProperty is what I need, but: 一些搜索建议我需要SetProperty / GetProperty ,但是:

var col = new TreeViewColumn("TreeItem", renderer);
col.AddAttribute(renderer, "tree-item", 0);

Throws an error on runtime since TreeItemCellRenderer has no property named "tree-item". 由于TreeItemCellRenderer没有名为“ tree-item”的属性,因此在运行时引发错误。 Also, it is worth noting that SetProperty is not virtual. 另外,值得注意的是SetProperty 不是虚拟的。

So how should I do it? 那我该怎么办呢?

Actually, the only problem is that defining the value/data to render in your custom cell renderer is not done in the renderer itself, but outside, in a listener method. 实际上,唯一的问题是,在自定义单元格渲染器中定义要渲染的值/数据不是在渲染器本身中完成,而是在侦听器方法中进行。

In your widget class, where you define the TreeView and its columns and CellRenderers, you can also define a TreeCellDataFunc, which is nothing but a wickedly hidden name for a listener function that is called before a cell is rendered. 在小部件类中,您可以在其中定义TreeView及其列和CellRenderers,还可以定义TreeCellDataFunc,它只是在呈现单元格之前调用的侦听器函数的邪恶隐藏名称。 But its name already has the "Data" inside and that is what you're supposed to do within that function: Supply the data to render. 但是其名称中已经包含“数据”,这就是您应该在该函数中执行的操作:提供要渲染的数据。

TreeItemCellRenderer cellRenderer = new TreeItemCellRenderer();
column.SetCellDataFunc(cellRenderer, new Gtk.TreeCellDataFunc(AwesomeDataFunction));

/**
* Supplies the TreeItemCellRenderer with data for the current cell.
* */
private void AwesomeDataFunction(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
{
    (cell as TreeItemCellRenderer).<some self-declared property> = <any fitting value>;
}

You will likely want use the iter and model to get the data that you want. 您可能需要使用迭代器和模型来获取所需的数据。 The actual Render() function of the CellRenderer is called after that function. 在该函数之后调用CellRenderer的实际Render()函数。

All in all, I think that whole TreeView/CellRenderer model is a mess. 总而言之,我认为整个TreeView / CellRenderer模型是一团糟。 While it does work and you can do most things with it, it is completely unclear what you are supposed to do to achieve your goals. 尽管它确实有效,并且您可以用它做大多数事情,但是完全不清楚应该如何实现目标。 That one TreeView tutorial is okay, but really only shows the tip of the iceberg. 那个TreeView教程还可以,但实际上只显示了冰山一角。 Why no Widgets are used for the cell rendering is beyond me. 为什么没有小部件用于单元格渲染超出了我的范围。 It would have been far easier. 这本来容易得多。

You just declare a property and use it like in this example. 您只需声明一个属性,然后像本例中一样使用它。

class CellRendererSimple : CellRenderer
{

//property asigned to by treeviewcolumn
//eg. TreeViewColumn tvc = new TreeViewColumn("Column 0", new CellRendererSimple(),"tree_item",0);
[GLib.Property("tree_item")] //this line seems to be nessasary for the property to be recognised by the treeviewcolumn.
    public string tree_item
    {
        get;
        set;
    }

    protected override void Render(Gdk.Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
    {
        //this seems to be the minimum to render text
        GC gc = widget.Style.TextGC(StateType.Normal);
        Pango.Layout layout = new Pango.Layout(widget.PangoContext);
        layout.SetText(tree_item);//add the text to thelayout.
        //this is the actuall rendering
        window.DrawLayout(gc, expose_area.X, expose_area.Y, layout);
    }
}

I haven't found an actual good answer, but I did find a workaround. 我没有找到实际的好答案,但是我确实找到了解决方法。

My goal has always been to display information while keeping a "pointer" to the class that owns that value. 我的目标一直是显示信息,同时保持拥有该值的类的“指针”。 So here's what I did: 所以这就是我所做的:

  1. Declare only one column (the "label") 仅声明一列(“标签”)
  2. Append rows, each with two columns - the label to display and the class instance. 追加行,每行列-要显示的标签和类实例。 That way the first row is displayed but the second is hidden 这样,显示第一行但隐藏第二行

Now, getting the second column of each row will give me the value I want, without having to deal with custom renderers and without having random data appearing in the tree. 现在,获取每一行的第二列将为我提供我想要的值, 无需处理自定义渲染器,也无需在树中显示随机数据。

I know this doesn't answer the question, but it does solve my particular problem. 我知道这不能解决问题,但确实可以解决我的特定问题。 In case someone else ends up in this page, I hope this information is still helpful. 如果其他人最终进入此页面,希望此信息对您有所帮助。 But if you do find a better solution, feel free to post it anyway. 但是,如果您找到更好的解决方案,请随时发布。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM