Пользовательские средства визуализации ячеек дерева в GTK # - Как получить данные ячейки? - PullRequest
2 голосов
/ 26 ноября 2011

Я использую TreeView в GTK #, и теперь мне нужно использовать пользовательское средство визуализации ячеек.

Хотя у меня есть почти все для работы, есть одна недостающая часть: средство визуализации ячеек должно знать, что отображать.

Данные для рендеринга являются пользовательским классом. Я хочу получить поле из этого класса.

Вот что у меня есть

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);
        }
    }
}

Теперь я хочу нарисовать свое поле вместо «Привет, мир!». Какой-то гугл предположил, что SetProperty / GetProperty - это то, что мне нужно, но:

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

Выдает ошибку во время выполнения, поскольку TreeItemCellRenderer не имеет свойства с именем "tree-item". Также стоит отметить, что SetProperty является , а не виртуальным.

Так как мне это сделать?

Ответы [ 3 ]

3 голосов
/ 25 марта 2012

На самом деле, единственная проблема заключается в том, что определение значения / данных, которые будут отображаться в вашем настраиваемом устройстве визуализации ячеек, выполняется не в самом устройстве визуализации, а снаружи, в методе слушателя.

В своем классе виджетов, где вы определяете TreeView и его столбцы и CellRenderers, вы также можете определить TreeCellDataFunc, который является не чем иным, как злонамеренно скрытым именем для функции слушателя, которая вызывается перед визуализацией ячейки. Но его имя уже содержит «Данные» внутри, и это то, что вы должны делать в этой функции: предоставить данные для рендеринга.

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>;
}

Вы, вероятно, захотите использовать iter и модель, чтобы получить данные, которые вы хотите. Фактическая функция Render () CellRenderer вызывается после этой функции.

В целом, я думаю, что вся модель TreeView / CellRenderer - беспорядок. Хотя он работает и вы можете делать с ним большинство вещей, совершенно неясно, что вы должны делать для достижения своих целей. Одно руководство по TreeView хорошо, но на самом деле показывает только верхушку айсберга. Почему никакие виджеты не используются для рендеринга ячеек, мне не под силу. Это было бы намного проще.

1 голос
/ 16 марта 2016

Вы просто объявляете свойство и используете его, как в этом примере.

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);
    }
}
0 голосов
/ 27 ноября 2011

Я не нашел правильного ответа, но нашел обходной путь.

Моя цель всегда состояла в том, чтобы отображать информацию, сохраняя при этом «указатель» на класс, которому принадлежит это значение. Итак, вот что я сделал:

  1. Объявить только один столбец («метка»)
  2. Добавить строки, каждая с двумя столбцами - метка для отображения и экземпляр класса. Таким образом, отображается первая строка, а вторая скрыта

Теперь, получение второго столбца каждой строки даст мне желаемое значение: без необходимости иметь дело с пользовательскими средствами визуализации и без появления случайных данных в дереве.

Я знаю, что это не отвечает на вопрос, но решает мою конкретную проблему. В случае, если кто-то еще окажется на этой странице, я надеюсь, что эта информация все еще полезна. Но если вы найдете лучшее решение, не стесняйтесь опубликовать его.

...