Search code examples
cgtkglade

Setting text of GTK+ entry or label isn't working


I'm simply trying to change the text inside a label taken from a text-enty widget on pressing Enter inside the text-entry widget. I'm using Glade to design this simplistic interface, containing only those two widgets inside an window. Then it's converted to GIO resource with glib-compile-resources test.xml and loaded into program.

But the label doesn't change. Any idea what I'm doing wrong? The compiler doesn't give any warning. I'm able to print the contents of the label as well, which I set from Glade.

test.c

#include <gtk/gtk.h>

static void on_entry_activate(GtkWidget *entry, gpointer data) {
    const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry));
    GtkBuilder *app_builder = gtk_builder_new_from_resource(
                              "/org/samik/test/test.glade");
    GObject *label = gtk_builder_get_object(app_builder, "label1");
    g_print("%s\n", gtk_label_get_text(GTK_LABEL(label)));
    gtk_label_set_text(GTK_LABEL(label), text);
}
static void on_app_activate(GApplication *app, gpointer data) {
    GError *res_load_err = NULL;
    GResource *app_res = g_resource_load("test.gresource", &res_load_err);
    g_resources_register(app_res);
    GtkBuilder *app_builder = gtk_builder_new_from_resource(
                              "/org/samik/test/test.glade");
    GObject *entry = gtk_builder_get_object(app_builder, "entry1");
    GObject *main_window = gtk_builder_get_object(app_builder, "window1");
    g_signal_connect(GTK_WIDGET(entry), "activate", 
        G_CALLBACK(on_entry_activate), NULL);
    gtk_window_set_application(GTK_WINDOW(main_window), GTK_APPLICATION(app));
    gtk_widget_show_all(GTK_WIDGET(main_window));
}
int main(int argc, char *argv[]) {
    int status;

    GtkApplication *app = gtk_application_new("org.samik.draw", 
                            G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, "activate", G_CALLBACK(on_app_activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);

    g_object_unref(app);

    return status;
}

test.glade

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.1 -->
<interface>
  <requires lib="gtk+" version="3.10"/>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <property name="title" translatable="yes">test</property>
    <child>
      <object class="GtkFixed" id="fixed1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
         <!-- take whatever user types in this text-entry -->
          <object class="GtkEntry" id="entry1">
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
          </object>
          <packing>
            <property name="x">197</property>
            <property name="y">119</property>
          </packing>
        </child>
        <child>
          <!-- and put it here -->
          <object class="GtkLabel" id="label1">
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">label</property>
          </object>
          <packing>
            <property name="x">53</property>
            <property name="y">56</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

test.xml

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
    <gresource prefix="/org/samik/test">
        <file compressed="true">test.glade</file>
    </gresource>
</gresources>

Solution

  • When you call gtk_builder_new_from_resource() twice, you are essentially creating two windows (but only showing one). The call that modifies the label is correct but it modifies the label in the invisible window.

    Load the resources only once in initialization and provide the callback functions with pointers to the actual widgets. Typically you'd create a struct with pointers to all widgets you are going to need later, and then pass a pointer to that struct as userdata to callback functions like on_entry_activate().