ccallbackgtkgnugtk4

unable to add label to box by the click of a button gtk4 in C


I have the following code, where I have a box containing a label, an entry, and a button. I set a callback function for the button that adds a label containing the text in the EntryBuffer. when I run it, type something in the entry, and click the button nothing happens.

#include <gtk/gtk.h>
#undef main

struct MyWidgets{
  GtkWidget* prompt;
  GtkWidget* box;
};

void on_button_clicked(GtkButton *button, gpointer data) {
    struct MyWidgets *widgets = (struct MyWidgets*) data;

    GtkEntryBuffer *buffer = gtk_entry_get_buffer((GtkEntry*)widgets->prompt);

    const char *text = gtk_entry_buffer_get_text(buffer);
  
    GtkWidget *output = gtk_label_new(text);
    gtk_widget_set_margin_start(output, 30);

    gtk_box_append((GtkBox*)widgets->box, output);

    gtk_widget_set_visible(output, TRUE);
}

static void on_activate (GtkApplication *app) {
    // Create a new window
    GtkWidget *window = gtk_application_window_new (app);

    // Set the default size of the window to 500x300
    gtk_window_set_resizable((GtkWindow*)window, FALSE);
    gtk_window_set_default_size((GtkWindow*)(window), 800, 900);

    // Create a vertical box to organize elements
    GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
    gtk_box_set_homogeneous((GtkBox*)box, FALSE);

    //create label
    GtkWidget *label = gtk_label_new("Enter ebnf expression :");
    gtk_label_set_xalign((GtkLabel*)label, 0);
    gtk_widget_set_margin_start(label, 30);

    // create input box 
    GtkWidget *prompt = gtk_entry_new();
    
    gtk_widget_set_size_request(prompt, 300, 40);
    gtk_widget_set_margin_start(prompt, 30);
    gtk_widget_set_margin_end(prompt, 30);

    // Create a new button
    GtkWidget *button = gtk_button_new_with_label ("Submit");
    gtk_button_set_has_frame((GtkButton*)button, TRUE);
    gtk_widget_set_margin_start(button, 300);
    gtk_widget_set_margin_end(button, 300);

    // Create a data structure to hold multiple pieces of data
    
    struct MyWidgets widgets;
    widgets.box = box;
    widgets.prompt = prompt;

    // Pack the text view and button into the vertical box
    gtk_box_append((GtkBox*)box, label);
    gtk_box_append((GtkBox*)box, prompt);
    gtk_box_append((GtkBox*)box, button);

    // When the button is clicked, close the window passed as an argument
    g_signal_connect((GtkButton*)button, "clicked", G_CALLBACK(on_button_clicked),&widgets);
    


    // Set the box as the child of the window
    gtk_window_set_child(GTK_WINDOW(window), box);

    gtk_window_present (GTK_WINDOW (window));
}

// main ....

I am new to gtk4, I wonder whether the issue relies in the elements in box not updating in the activate function. in the old version there is a show.all method i guess, but in gtk4 there is set_visible, which I already set for label in the callback function, but it still hasn't resolved the problem


Solution

  • There is already a similar question here: Passing callback arguments through GTK's g_signal_connect() leads to unexpected values in C , which was answered by Ted Lyngmo here. https://stackoverflow.com/a/77149801 For your problem, I would suggest the following changes:

    typedef struct {
      GtkWidget* prompt;
      GtkWidget* box;
    } MyWidgets;
    

    and

    void on_button_clicked(GtkButton *button, gpointer data) {
        MyWidgets *widgets = (MyWidgets*) data;
     ...
    

    and

    // Create a data structure to hold multiple pieces of data
        static MyWidgets widgets;
        MyWidgets *widgets_ptr =&widgets ;
        widgets_ptr->box = box;
        widgets_ptr->prompt = prompt;
    

    and

    // When the button is clicked, close the window passed as an argument
    g_signal_connect((GtkButton*)button, "clicked", G_CALLBACK(on_button_clicked),widgets_ptr);