使用gtkmm创建Glade构建的TreeView [英] Glade-constructed TreeView with gtkmm

查看:259
本文介绍了使用gtkmm创建Glade构建的TreeView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



这是经理的类:

我有一个glade构建的TreeView / ListStore,我试图加载到应用程序并通过gtkmm操作。 / p>

  typedef struct 
{
Gtk :: ListStore * liststore_info;
Gtk :: TreeModelColumn< string> * treeview_info_column_time;
Gtk :: TreeModelColumn< string> * treeview_info_column_message;
} UiElements;

class GuiManager
{
Glib :: RefPtr< Gtk :: Builder>构建器
UiElements elements;

public:
GuiManager();
〜GuiManager();

void info_handler(string msg);
}

而实现:

  GuiManager :: GuiManager()
{
builder = Gtk :: Builder :: create();
builder-> add_from_file(GUI.glade);

builder-> get_widget(liststore_info,elements.liststore_info);
builder-> get_widget(treeview_info_column_time,elements.treeview_info_column_time);
builder-> get_widget(treeview_info_column_message,elements.treeview_info_column_message);
}

这里是我试图调用以操作TreeView的函数:

  void GuiManager :: info_handler(string msg)
{
Gtk :: TreeModel :: Row row = (elements.liststore_info-> append());
row [*(elements.treeview_info_column_time)] =现在;
row [*(elements.treeview_info_column_message)] = msg;
}

最后,相关的Glade XML:

 < object class =GtkListStoreid =liststore_info> 
< columns>
<! - column-name Time - >
< column type =string/>
<! - column-name Message - >
< column type =string/>
< / columns>
< / object>
< object class =GtkTreeViewid =treeview_info>
< property name =visible> True< / property>
< property name =can_focus> True< / property>
< property name =model> liststore_info< / property>
< property name =enable_search> False< / property>
< property name =enable_grid_lines> both< / property>
< child internal-child =selection>
< object class =GtkTreeSelectionid =treeview-selection2/>
< / child>
< child>
< object class =GtkTreeViewColumnid =treeview_info_column_time>
< property name =resizable> True< / property>
< property name =sizing> autosize< / property>
< property name =min_width> 100< / property>
< property name =titletranslatable =yes>时间< / property>
< property name =clickable> True< / property>
< / object>
< / child>
< child>
< object class =GtkTreeViewColumnid =treeview_info_column_message>
< property name =resizable> True< / property>
< property name =sizing> autosize< / property>
< property name =min_width> 300< / property>
< property name =titletranslatable =yes> Message< / property>
< property name =clickable> True< / property>
< / object>
< / child>
< / object>

但是,编译失败,并带有以下内容:

 在/usr/include/gtkmm-3.0/gtkmm.h:119:0包含的文件中,
来自GUI3_gui_manager.h:8,
GUI3_gui_manager.cpp:1:
/usr/include/gtkmm-3.0/gtkmm/builder.h:在实例化'void Gtk :: Builder :: get_widget(const Glib :: ustring& T_Widget *&) [with T_Widget = Gtk :: TreeModelColumn< std :: basic_string< char> >]':
GUI3_gui_manager.cpp:64:86:从这里需要
/usr/include/gtkmm-3.0/gtkmm/builder.h:628:93:error:'get_base_type'is not 'Gtk :: TreeModelColumn< std :: basic_string< char>的成员>'
widget = dynamic_cast< T_Widget *>(this-> get_widget_checked(name,T_Widget :: get_base_type()));
^



我明显错误地使用TreeModelColumn,但我的源代码教程这种方法(迄今为止证明是可靠的)以类似的方式做事情,所以我在亏损正确的方法在这里。



任何帮助是赞赏。 =)

解决方案

我刚刚制定了如何做到这一点。因为你必须创建一个与.glade文件中的类型相匹配的C ++类,但是如果它们匹配,你会得到和手动创建TreeView时一样的类型安全函数。

  class Cols:public Gtk :: TreeModel :: ColumnRecord {
public:
Cols(){
//此顺序必须与.glade文件中的列顺序匹配
this-> add(this-> colA);
this-> add(this-> colB);
this-> add(this-> colC);
}

//这些类型必须与.glade文件中的模型匹配
Gtk :: TreeModelColumn< Glib :: ustring>可乐;
Gtk :: TreeModelColumn< Glib :: ustring> colB;
Gtk :: TreeModelColumn< Glib :: ustring> colC;
};

...

//从.glade文件获取TreeView
Gtk :: TreeView * tv = nullptr;
refBuilder-> get_widget(treeview1,tv); // refBuilder是Gtk :: Builder实例
assert(tv);

//从.glade文件获取ListStore模型
auto items = Glib :: RefPtr< Gtk :: ListStore> :: cast_dynamic(
refBuilder-> get_object(listmodel1)
);
assert(items);

Cols mycols;

//用项目填充树视图
auto row = *(items-> append());
row [mycols.colA] =第1行1;
row [mycols.colB] =第1行第2列;

row = *(items-> append());
row [mycols.colA] =第2行1;

这可以通过 Cols :: Cols()以与.glade文件相同的顺序添加类型安全列,因此每个 colX 变量中存储的索引与在.glade文件中的相应索引中的数据类型匹配。模型。只要不要忘记更新代码,如果你重新排序列!你甚至可以在Glade中的TreeView中添加一些项目,然后在代码中追加更多的项目,并且它们都将在运行时显示在一起!



从阅读文档看起来像你也可以使用type-unsafe set_value()函数,如果你想避免创建 Cols this:(未测试)

  row.set_value(0,第一列的值 
row.set_value(1,第二列的值);

文档警告,如果数据类型与预期列不匹配,格式,所以去创建类 Cols 的努力可能是值得的。


I've got a glade-constructed TreeView/ListStore that I'm trying to load into an application and manipulate via gtkmm.

Here's the manager's class:

typedef struct
{
  Gtk::ListStore *liststore_info;
  Gtk::TreeModelColumn<string> *treeview_info_column_time;
  Gtk::TreeModelColumn<string> *treeview_info_column_message;
}UiElements;

class GuiManager
{
  Glib::RefPtr<Gtk::Builder> builder;
  UiElements elements;

  public:
    GuiManager();
    ~GuiManager();

    void info_handler(string msg);
}

And the implementation:

GuiManager::GuiManager()
{
  builder = Gtk::Builder::create();
  builder->add_from_file("GUI.glade");

  builder->get_widget("liststore_info", elements.liststore_info);
  builder->get_widget("treeview_info_column_time", elements.treeview_info_column_time);
  builder->get_widget("treeview_info_column_message", elements.treeview_info_column_message);
}

Here's the function I'm trying to call to manipulate the TreeView:

void GuiManager::info_handler(string msg)
{
  Gtk::TreeModel::Row row = *(elements.liststore_info->append());
  row[*(elements.treeview_info_column_time)] = "Now";
  row[*(elements.treeview_info_column_message)] = msg;
}

And finally, the relevant Glade XML:

<object class="GtkListStore" id="liststore_info">
  <columns>
    <!-- column-name Time -->
    <column type="string"/>
    <!-- column-name Message -->
    <column type="string"/>
  </columns>
</object>
<object class="GtkTreeView" id="treeview_info">
  <property name="visible">True</property>
  <property name="can_focus">True</property>
  <property name="model">liststore_info</property>
  <property name="enable_search">False</property>
  <property name="enable_grid_lines">both</property>
  <child internal-child="selection">
    <object class="GtkTreeSelection" id="treeview-selection2"/>
  </child>
  <child>
    <object class="GtkTreeViewColumn" id="treeview_info_column_time">
      <property name="resizable">True</property>
      <property name="sizing">autosize</property>
      <property name="min_width">100</property>
      <property name="title" translatable="yes">Time</property>
      <property name="clickable">True</property>
    </object>
  </child>
  <child>
    <object class="GtkTreeViewColumn" id="treeview_info_column_message">
      <property name="resizable">True</property>
      <property name="sizing">autosize</property>
      <property name="min_width">300</property>
      <property name="title" translatable="yes">Message</property>
      <property name="clickable">True</property>
    </object>
  </child>
</object>

The compilation fails, however, with the following:

In file included from /usr/include/gtkmm-3.0/gtkmm.h:119:0,
                 from GUI3_gui_manager.h:8,
                 from GUI3_gui_manager.cpp:1:
/usr/include/gtkmm-3.0/gtkmm/builder.h: In instantiation of ‘void Gtk::Builder::get_widget(const Glib::ustring&, T_Widget*&) [with T_Widget = Gtk::TreeModelColumn<std::basic_string<char> >]’:
GUI3_gui_manager.cpp:64:86:   required from here
/usr/include/gtkmm-3.0/gtkmm/builder.h:628:93: error: ‘get_base_type’ is     not a member of ‘Gtk::TreeModelColumn<std::basic_string<char> >’
     widget = dynamic_cast<T_Widget*>(this->get_widget_checked(name, T_Widget::get_base_type()));
                                                                                             ^

I'm obviously misusing TreeModelColumn, but my source tutorial for this method (which as thus far proven reliable) does things in a similar fashion, so I'm at a loss for the correct method here.

Any help is appreciated. =)

解决方案

I've just worked out how to do this. It's slightly dodgy as you have to create a C++ class that matches the types in your .glade file, but providing they do match, you get the same type-safe functions as you do when creating the TreeView manually.

class Cols: public Gtk::TreeModel::ColumnRecord {
    public:
        Cols() {
            // This order must match the column order in the .glade file
            this->add(this->colA);
            this->add(this->colB);
            this->add(this->colC);
        }

        // These types must match those for the model in the .glade file
        Gtk::TreeModelColumn<Glib::ustring> colA;
        Gtk::TreeModelColumn<Glib::ustring> colB;
        Gtk::TreeModelColumn<Glib::ustring> colC;
};

...

// Get hold of the TreeView from the .glade file
Gtk::TreeView* tv = nullptr;
refBuilder->get_widget("treeview1", tv); // refBuilder is Gtk::Builder instance
assert(tv);

// Get hold of the ListStore model from the .glade file
auto items = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(
    refBuilder->get_object("listmodel1")
);
assert(items);

Cols mycols;

// Populate tree view with items
auto row = *(items->append());
row[mycols.colA] = "Row 1 Col 1";
row[mycols.colB] = "Row 1 Col 2";

row = *(items->append());
row[mycols.colA] = "Row 2 Col 1";

This works by Cols::Cols() adding the type-safe columns in the same order as the .glade file, so the index stored in each of the colX variables matches the data type in the corresponding index in the model. Just don't forget to update the code if you ever reorder the columns! You can even add some items to the TreeView within Glade, then append more items in code and they will all show up together at runtime!

From reading the docs it looks like you could also use the type-unsafe set_value() function if you wanted to avoid creating the Cols class entirely, like this: (untested)

row.set_value(0, "value for first column");
row.set_value(1, "value for second column");

The docs warn that a crash is likely to result if the data type doesn't match the expected column format, so going to the effort of creating a class like Cols is probably worth it.

这篇关于使用gtkmm创建Glade构建的TreeView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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