c - 以编程方式将数据添加到在 Glade 3.12.1 中创建的 GtkTreeView/GtkListStore

标签 c gtk gtk3 glade gtktreeview

我一直在自学如何用 C 语言编写代码,并利用 GTK 在 Linux 中编写应用程序,在实现之前使用 Glade 设计 UI。我一直在尝试利用 GtkTreeView 与 GtkListStore 结合来显示数据,但我似乎遇到了问题。我可以让我的应用程序正常启动,并正确显示窗口和对话框,但我无法弄清楚如何以编程方式将数据行添加到列表存储并让它们显示在 TreeView 中;我发现大多数教程似乎更喜欢在 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;
}

林间空地文件(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>

最佳答案

将行附加到 TreeView 的代码基本上没问题,但有几个问题阻止它工作。

  1. 您正在 on_postingButton_clicked 的每个条目上创建并填充一个新的构建器。这显然是不正确的,因为这意味着每次单击“发布”按钮时都会创建一个新树和一个新商店。通过发送 treeview1 可以轻松解决此问题如user_dataon_postingButton_clicked打回来。您已经在 dialog 中这样做了,所以我简单修改了<signal name="clicked" handler="on_postingButton_clicked" ...>在您的 XML 中还包括 object="treeview1" .

  2. 你对 g_object_unref 太自由了。 gtk_tree_view_get_model不会增加其模型的引用计数,因此您不应该取消引用您获得的列表存储。取消引用 main 中的构建器如果您想传递它并从中检索对象(无论如何它是一个单例),这可能是一个坏主意。

  3. 你应该#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;
}

关于c - 以编程方式将数据添加到在 Glade 3.12.1 中创建的 GtkTreeView/GtkListStore,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17370162/

相关文章:

c - 变量和函数名称的范围

c - C 无法显示文件内容

Python + pygtk 从数据库生成复选框表

python-3.x - Python websockets 和 gtk - 对 asyncio 队列感到困惑

C-GTK-g_application_quit

C 编程 - 初始化结构二维数组

c++ - CMake 的默认构建目标的名称是什么?

gtk - 使用 Glade 在 Gtk TreeView 中创建带有可编辑单元格的列

c++ - 错误 : void value not ignored as it ought to be - C/GTK+

python - 无法在 Gtk.TextView i Python 3 中对列进行排序