У меня есть TreeView / ListStore, созданный на поляне, который я пытаюсь загрузить в приложение и манипулировать через gtkmm.
Вот класс менеджера:
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);
}
И реализация:
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)] = "Now";
row[*(elements.treeview_info_column_message)] = msg;
}
И наконец, соответствующий 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>
Однако компиляция завершается неудачно со следующим:
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()));
^
Я явно неправильно использую TreeModelColumn, но мой исходный учебник для этого метода (который на данный момент доказал свою надежность) все происходит аналогичным образом, поэтому я не могу найти правильный метод здесь.
Любая помощь приветствуется. знак равно
Я только что понял, как это сделать. Это немного хитроумно, так как вам нужно создать класс C ++, который соответствует типам в вашем файле .glade, но если они совпадают, вы получаете те же функции безопасности типов, что и при создании TreeView вручную.
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";
Это работает Cols::Cols()
добавление типобезопасных столбцов в том же порядке, что и файл .glade, чтобы индекс сохранялся в каждом из colX
переменные соответствуют типу данных в соответствующем индексе в модели. Только не забудьте обновить код, если вы когда-нибудь измените порядок столбцов! Вы даже можете добавить некоторые элементы в TreeView в Glade, а затем добавить больше элементов в код, и все они будут отображаться вместе во время выполнения!
Из чтения документов похоже, что вы также можете использовать небезопасный тип set_value()
функционировать, если вы хотите избежать создания Cols
класс полностью, как это: (не проверено)
row.set_value(0, "value for first column");
row.set_value(1, "value for second column");
Документы предупреждают, что сбой может произойти, если тип данных не соответствует ожидаемому формату столбца, поэтому нужно приложить усилия для создания такого класса, как Cols
вероятно стоит того.
Обычно вы не можете определить TreeModel (ListStore, TreeStore) в Glade при использовании gtkmm. Типы C (используемые в Glade) и C ++ слишком разные, и API C ++ со статической типизацией не может знать об определении TreeModel вашего glade-файла во время компиляции.
Кроме того, в вашем коде ваш treeview_info_column_time в вашем коде C ++ является Gtk :: TreeModelColumn<>. Ваше treeview_info_column_time в вашем файле Glade является GtkTreeViewColumn. Столбцы модели и столбцы вида — это очень разные вещи. Вы можете просто использовать get_widget (), чтобы превратить одно в другое.
Вы также пытаетесь использовать get_widget (), чтобы получить свой listtore_info TreeModel (ListStore). Но TreeModel не является виджетом. get_object () может работать, но я бы не стал пытаться определить модель в Glade. Учебник, на который вы ссылаетесь, тоже этого не делает.