Программно добавляем данные в GtkTreeView/GtkListStore, созданный в Glade 3.12.1
Я учил себя, как кодировать на C и использовать GTK для написания приложений в Linux, используя Glade для разработки пользовательского интерфейса перед его реализацией. Я пытался использовать GtkTreeView в сочетании с GtkListStore для отображения данных, но я, кажется, сталкиваюсь с проблемами. Я могу заставить мое приложение нормально запускаться, и оно правильно отображает окно и диалог, но я не могу понять, как программно добавлять строки данных в хранилище списков и отображать их в древовидном представлении; большинство учебных пособий, которые я нахожу, предпочитают создавать строки в Glade или разрабатывать весь интерфейс с помощью кода. С кодом, как он есть, я не получаю ошибок при запуске программы, но я не вижу ничего добавляемого в GtkTreeView. Я не вижу добавленных пустых строк.
Написав некоторый код для принудительного генерирования ошибки, я вижу, что сигнал для postingButton
подключен (я думаю), так что должно быть хорошо. Я просто что-то упустил в моей реальной реализации GtkTreeView. Если кто-нибудь может мне помочь, я был бы очень признателен!
Изменить: GtkEntries, которые присутствуют, будут реализованы позже; Я просто пытаюсь получить данные, чтобы показать на всех.
Код C:
/* I'd give objects better names normally, no worries!
* Just goofing around for now.*/
#include <gtk-3.0/gtk/gtk.h> // Needed for interface.
#include <gtk-3.0/gdk/gdk.h>
#include <glib-2.0/glib-object.h>
void on_mainWindow_destroy(GObject *object, gpointer user_data)
{
gtk_main_quit();
}
void on_stupidButton_clicked(GtkButton *button, gpointer *user_data)
{
gtk_dialog_run(GTK_DIALOG(user_data));
}
void on_postingButton_clicked(GtkButton *button, gpointer *user_data)
{
GtkListStore *liststore1;
GtkWidget *treeview1; // I've tried defining this as a GtkTreeView as well.
GtkTreeIter iter;
GtkBuilder *listStoreBuilder;
listStoreBuilder = gtk_builder_new();
gtk_builder_add_from_file(listStoreBuilder,
"../testing_interface.glade", 0);
treeview1 = GTK_WIDGET(gtk_builder_get_object(listStoreBuilder,
"treeview1")); // I'd change this to GTK_TREE_VIEW if the
// above is a GtkTreeView.
liststore1 = GTK_LIST_STORE(
gtk_tree_view_get_model((GtkTreeView *)treeview1));
gtk_list_store_append(liststore1, &iter);
gtk_list_store_set(liststore1, &iter, 0, "c", 1, "d", -1);
gtk_builder_connect_signals(listStoreBuilder, 0);
g_object_unref(G_OBJECT(listStoreBuilder));
g_object_unref(G_OBJECT(liststore1));
}
void on_cancelButton_clicked(GtkButton *button, gpointer *user_data)
{
gtk_widget_destroy((GtkWidget *)user_data);
}
int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *mainWindow, *dumbDialog;
GtkButton *stupidButton;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "../testing_interface.glade",
0);
mainWindow = GTK_WIDGET(gtk_builder_get_object(builder, "mainWindow"));
stupidButton = GTK_BUTTON(gtk_builder_get_object(builder, "stupidButton"));
dumbDialog = GTK_WIDGET(gtk_builder_get_object(builder, "dumbDialog"));
gtk_builder_connect_signals(builder, 0);
g_object_unref(G_OBJECT(builder));
gtk_widget_show(mainWindow);
gtk_main();
return 0;
}
Файл Glade (testing_interface.glade):
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkDialog" id="dumbDialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="postingButton">
<property name="label" translatable="yes">Post</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_postingButton_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cancelButton">
<property name="label" translatable="yes">Cancel</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_cancelButton_clicked" object="dumbDialog" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">postingButton</action-widget>
<action-widget response="0">cancelButton</action-widget>
</action-widgets>
</object>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name Testing -->
<column type="gchararray"/>
<!-- column-name Testing1 -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkWindow" id="mainWindow">
<property name="can_focus">False</property>
<signal name="destroy" handler="on_mainWindow_destroy" swapped="no"/>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkTreeView" id="treeview1">
<property name="height_request">183</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">liststore1</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="testing1Col">
<property name="title" translatable="yes">column</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="testing2Col">
<property name="title" translatable="yes">column</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="stupidButton">
<property name="label" translatable="yes">button</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_stupidButton_clicked" object="dumbDialog" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
1 ответ
Ваш код, который добавляет строки в древовидное представление, в основном нормальный, но некоторые проблемы не позволяют ему работать.
Вы создаете и заполняете нового строителя в каждой записи
on_postingButton_clicked
, Это, очевидно, неверно, потому что это означает, что вы создаете новое дерево и новый магазин при каждом нажатии кнопки "Отправить". Это легко исправить отправкойtreeview1
какuser_data
кon_postingButton_clicked
Перезвоните. Вы делаете это уже вdialog
так я просто модифицировал<signal name="clicked" handler="on_postingButton_clicked" ...>
в вашем XML, чтобы также включитьobject="treeview1"
,Вы слишком либеральны с
g_object_unref
,gtk_tree_view_get_model
не увеличивает refcount своей модели, поэтому вы не должны разыскивать список списков, который вы получаете. Unrefing строитель вmain
Вероятно, это плохая идея, если вы хотите передать его и извлечь из него объекты (и это в любом случае одиночка).Вы должны
#include <gtk/gtk.h>
без вмешательстваgtk-3.0
каталог. Если ваша компиляция не удалась без этого, вы, вероятно, не настраиваетеpkg-flags
правильно.
Вот модифицированная версия вашего кода, которая работает для меня. Требуется изменить XML, как описано выше.
/* compile with:
gcc -O2 -Wall glade-test.c $(pkg-config gtk+-3.0 gmodule-export-2.0 --cflags --libs) */
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib-object.h>
void on_mainWindow_destroy(GObject *object, gpointer user_data)
{
gtk_main_quit();
}
void on_stupidButton_clicked(GtkButton *button, gpointer *user_data)
{
gtk_dialog_run(GTK_DIALOG(user_data));
}
void on_postingButton_clicked(GtkButton *button, gpointer *user_data)
{
GtkTreeIter iter;
GtkTreeView *treeview1 = GTK_TREE_VIEW(user_data);
GtkListStore *liststore1 = GTK_LIST_STORE(gtk_tree_view_get_model(treeview1));
gtk_list_store_append(liststore1, &iter);
gtk_list_store_set(liststore1, &iter, 0, "c", 1, "d", -1);
}
void on_cancelButton_clicked(GtkButton *button, gpointer *user_data)
{
gtk_widget_destroy((GtkWidget *)user_data);
}
int main(int argc, char *argv[])
{
GtkBuilder *builder;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "testing_interface.glade", 0);
gtk_builder_connect_signals(builder, 0);
gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(builder, "mainWindow")));
g_object_unref(G_OBJECT(builder));
gtk_main();
return 0;
}