Gtk4 C get text from entry

Please could anybody helps how to get text from entry.

my App do not throw any error, but do not return any text :frowning:

I am expecting that app writes to stdout text from entry, when i press button “aktualizuj” to call function:
static void aktualizuj (GtkWidget *widget, gpointer data)

my code:

#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include <string>
#include <iostream>

using namespace std;

static void aktualizuj (GtkWidget *widget, gpointer   data) {
  cout << "update" << endl;

  GtkBuilder *builder = gtk_builder_new ();
  gtk_builder_add_from_file (builder, "rozlozeni.ui", NULL);

  GObject *entry = gtk_builder_get_object (builder, "entry");

  string prectenejText = gtk_editable_get_text(GTK_EDITABLE(entry));

  cout << "readed text from entry: " << prectenejText << "-*-" << endl;

  g_object_unref (builder);
}

static void quit_cb (GtkWindow *window) {
  gtk_window_close (window);
}

static void activate (GtkApplication *app, gpointer user_data) {
  /* Construct a GtkBuilder instance and load our UI description */
  GtkBuilder *builder = gtk_builder_new ();
  gtk_builder_add_from_file (builder, "rozlozeni.ui", NULL);

  cout << "after builder" << endl;

  /* Connect signal handlers to the constructed widgets. */
  GObject *window = gtk_builder_get_object (builder, "window");
  gtk_window_set_application (GTK_WINDOW (window), app);

  cout << "after window" << endl;

  GObject *button = gtk_builder_get_object (builder, "aktualizuj");
  g_signal_connect (button, "clicked", G_CALLBACK (aktualizuj), NULL);

  cout << "after button" << endl;

  button = gtk_builder_get_object (builder, "ukonci");
  g_signal_connect_swapped (button, "clicked", G_CALLBACK (quit_cb), window);

  gtk_widget_show (GTK_WIDGET (window));

  /* We do not need the builder any more */
  g_object_unref (builder);
}

int main (int   argc,  char *argv[]) {
#ifdef GTK_SRCDIR
  g_chdir (GTK_SRCDIR);
#endif

  GtkApplication *app = gtk_application_new ("pokusna.testovaci.apka", G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);

  int status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}

and my rozlozeni.ui file:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk" version="4.0"/>
  <object class="GtkWindow" id="window">
    <property name="child">
      <object class="GtkBox">
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkLabel" id="label">
            <property name="label" translatable="1">label</property>
          </object>
        </child>
        <child>
          <object class="GtkLabel">
            <property name="label" translatable="1">neco napis</property>
          </object>
        </child>
        <child>
          <object class="GtkEntry" id="entry">
            <property name="focusable">1</property>
          </object>
        </child>
        <child>
          <object class="GtkButton" id="aktualizuj">
            <property name="label" translatable="1">aktualizuj</property>
            <property name="focusable">1</property>
            <property name="receives-default">1</property>
          </object>
        </child>
        <child>
          <object class="GtkButton" id="ukonci">
            <property name="label" translatable="1">ukonci</property>
            <property name="focusable">1</property>
            <property name="receives-default">1</property>
          </object>
        </child>
      </object>
    </property>
  </object>
</interface>

Hello,

The thing is that in your aktualizuj() function you’re re-creating a new set of widgets with gtk_builder_new(). All gtk_builder_new() does is taking a UI definition and creating it, so calling it multiple times will just create multiple widget sets, not shared at all.

What you need is get the actual entry you’re initial UI is using. The easier is to pass it as user data (the gpointer data parameter) to your callback, and use that:

static void aktualizuj (GtkWidget *widget, gpointer data) {
  GtkWidget *entry = static_cast<GtkWidget*>(data);

  std::cout << "entry text is: " << gtk_editable_get_text(GTK_EDITABLE(entry)) << std::endl;
}

// ...
  g_signal_connect (button, "clicked", G_CALLBACK (aktualizuj), gtk_builder_get_object(builder, "entry"));
// ...

But with more complex setups, you might want to store the widgets you need in a structure (or class as you’re actually using C++) and pass that around your callbacks.

Great! that works.

and if I need more than one widget to pass to calback function. Is correct pass whole builder with:

g_signal_connect (button, "clicked", G_CALLBACK (aktualizuj), builder);

and in callback function get widgets with gtk_builder_get_object ?

ofcourse delete part of code:

g_object_unref (builder);

at the and of function “activate”.

Is this technique the correct one (I have tested, that it works)?

thank a lot

Well, it would work, but it’s not really an idiomatic way of doing it, no. As said, usually you’ll keep a reference (pointer, using the C API) to the widgets you care about in a structure or class, and use those pointers to refer to the widgets – and get rid of the GtkBuilder itself that has done its thing. E.g. you’d have a structure or class representing your application’s window and it would have reference to everything useful.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.