首页 > 解决方案 > 选择值时显示额外列的 Vala 组合框

问题描述

使用 valadoc 上的下拉示例,有一个下拉列表,每行显示两列数据。我正在寻找一个组合框,在选择一个值时显示两列,但在选择后隐藏第二列。我尝试了以下方法:

Gtk.ComboBox combo = new Gtk.ComboBox.with_model(list_store);

Gtk.CellRendererText name_renderer = new Gtk.CellRendererText();
combo.pack_start(name_renderer, true);
combo.add_attribute(name_renderer, "text", 0);
Gtk.CellRendererText shortcut_renderer = new Gtk.CellRendererText();
combo.pack_start(shortcut_renderer, true);
combo.add_attribute(shortcut_renderer, "text", 1);

combo.popup.connect(() => {
    combo.add_attribute(shortcut_renderer, "text", 1);
});
combo.popdown.connect(() => {
    combo.clear_attributes(shortcut_renderer);
    return true;
});

但是,这会产生以下错误:

Gtk-CRITICAL **: 21:46:08.050: gtk_list_store_get_value: assertion 'column < priv->n_columns' failed

GLib-GObject-CRITICAL **: 21:46:08.050: g_value_transform: assertion 'G_IS_VALUE (src_value)' failed

这些错误让我觉得我可能会以错误的方式解决这个问题,有人对如何实现这一点有任何指示吗?

标签: linuxcomboboxvala

解决方案


Gtk.ComboBox信号popuppopdown是键绑定信号,这意味着它们只会由键盘触发。这也意味着对于您所追求的行为没有简单的解决方案。可见性本身很容易。

需要一个布尔类型的list_store新列来控制渲染器的可见性:

Gtk.ListStore list_store = new Gtk.ListStore (3, typeof (string), typeof (int), typeof (bool));

然后,将 visible 属性添加到要隐藏的渲染器中:

box.add_attribute (renderer, "visible", 2);

然后,控制行为的信号必须迭代存储/模型并设置可见性:

    list_store.foreach ((model, path, iter) => {
        list_store.set (iter, 2, true); // true to show, false to hide
        return false;
    });

如前所述,信号不合适,但这里有一个简单的示例,它仅适用于键盘(按 Enter 或空格键)以弹出组合框并选择不同的活动行将恢复可见性。不完全是您想要的,但显示了需要在列表存储中完成的操作:

public class Application : Gtk.Window {
    public Application () {
        // Prepare Gtk.Window:
        this.title = "My Gtk.ComboBox";
        this.window_position = Gtk.WindowPosition.CENTER;
        this.destroy.connect (Gtk.main_quit);

        // Create & fill a ListStore:
        Gtk.ListStore list_store = new Gtk.ListStore (3, typeof (string), typeof (int), typeof (bool));
        Gtk.TreeIter iter;

        list_store.append (out iter);
        list_store.set (iter, 0, "Burgenland", 1, 13, 2, false);
        list_store.append (out iter);
        list_store.set (iter, 0, "Carinthia", 1, 17, 2, false);

        // The Box:
        Gtk.ComboBox box = new Gtk.ComboBox.with_model (list_store);
        this.add (box);

        Gtk.CellRendererText renderer = new Gtk.CellRendererText ();
        box.pack_start (renderer, true);
        box.add_attribute (renderer, "text", 0);
        box.active = 0;

        renderer = new Gtk.CellRendererText ();
        box.pack_start (renderer, true);
        box.add_attribute (renderer, "text", 1);
            box.add_attribute (renderer, "visible", 2);
        box.active = 0;

        box.changed.connect (() => {
            Value val1;
            Value val2;

            box.get_active_iter (out iter);
            list_store.get_value (iter, 0, out val1);
            list_store.get_value (iter, 1, out val2);

            print ("Selection: %s, %d\n", (string) val1, (int) val2);
            liststore_set_visibility (list_store, false);
        });

        box.popup.connect (() => {
            print ("PopUp signal...\n");
            liststore_set_visibility (list_store, true);
        });


        box.popdown.connect (() => {
            print ("PopDown signal...\n");
            return true;
        });
    }

    private static void liststore_set_visibility (Gtk.ListStore list_store, bool visible) {
        list_store.foreach ((model, path, iter) => {
            list_store.set (iter, 2, visible);
            return false;
        });
    }

    public static int main (string[] args) {
        Gtk.init (ref args);

        Application app = new Application ();
        app.show_all ();
        Gtk.main ();
        return 0;
    }
}

推荐阅读