Alfredo Miranda
Alfredo Miranda

Reputation: 108

How to get the text of a button in GTK?

I am developing an application that has a numeric keypad and a text box when clicked on a button, text box shows the number. I need to write a function to each button? Or you can pass a text and a widget as parameter?

#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>

void callback( GtkWidget *widget,
               gpointer   data )
{
   gtk_entry_append_text(entry, text);
}

void create_button(GtkWidget* table,GtkWidget* entry,
                    int start_r,int end_r,
                    int start_c,int end_c,
                    char* label)
{
    GtkWidget *button;

    button = gtk_button_new_with_label (label);
    g_object_set_data( G_OBJECT( button ),
                           "char", (gpointer)label );
    g_signal_connect (button, "clicked",
              G_CALLBACK (callback), entry);

    gtk_table_attach_defaults (GTK_TABLE(table), button, start_c, end_c, start_r, end_r);

    gtk_widget_show (button);

}

gint delete_event( GtkWidget *widget,
                   GdkEvent  *event,
                   gpointer   data )
{
    gtk_main_quit ();
    return(FALSE);
}

int main(int argc,char* argv[]){

    GtkWidget *window;
    //GtkWidget *button;
    GtkWidget *table;
    GtkWidget *entry;
    //GtkWidget *label;

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "Armario");
    g_signal_connect (GTK_OBJECT (window), "delete_event",
                        G_CALLBACK (delete_event), NULL);
    gtk_container_set_border_width (GTK_CONTAINER (window), 20);

    table = gtk_table_new (2, 2, TRUE);
    gtk_container_add (GTK_CONTAINER (window), table);

    entry = gtk_entry_new();
    gtk_entry_set_max_length(GTK_ENTRY(entry),10);
    gtk_entry_set_placeholder_text(GTK_ENTRY(entry),"Teste");
    gtk_table_attach_defaults (GTK_TABLE(table), entry, 0, 2, 1, 2);
    gtk_widget_show(entry);

    create_button(table,entry,0,1,0,1,"Botao");

    gtk_widget_show (table);
    gtk_widget_show (window);

    gtk_main ();

    return 0;
}

Upvotes: 6

Views: 8242

Answers (2)

liberforce
liberforce

Reputation: 11454

The answer to your question is yes, you can pass a widget in Gtk+ to a callback. Actually, the first parameter of the callback for the clicked signal is the button which received the signal (ie. usually the button that was clicked). As you can see in the sample code below, you can extract from the button its label and use it as text.

[...] /* In create_button... */
/* Make your buttons be notified when they are clicked */
g_signal_connect (button, "clicked", G_CALLBACK (on_button_clicked), entry);
[...]

/* Append the text in the button to the text entry */
void on_button_clicked (GtkButton *button, gpointer user_data)
{
    GtkEntry *entry = user_data;
    const gchar *text = gtk_button_get_label (button);
    gint position = 0;
    gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &position);
}

I'm using gtk_editable_insert_text because gtk_entry_append_text has been deprecated for a long time. Passing the "entry" parameter to the callback is possible by using the last parameter of g_signal_connect which allows you to specify some data that you need to access in your callback. This info is then made available to the callback in the "user_data" parameter.

Your exemple could also be improved by using gtk_widget_show_all, and I also don't see the point in calling g_object_set_data on the "char" property, as the text is already set in the label property (and retrieved with gtk_button_get_label).

Upvotes: 9

rodrigo
rodrigo

Reputation: 98348

Two options, that I can think of:

  1. GTK widgets are really GObjects, so you can attach to them arbitrary pieces of data. See the functions g_object_set_data/g_object_set_data_full/g_object_get_data. So you can just add the text to the button as an attached data and retrieve it when needed.

  2. You can pass any data you need to a callback by defining a struct with all the fields, and passing a pointer to it. If the struct cannot be declared statically, you can malloc it and use g_signal_connect_data to specify the function to release the data:

For example:

struct entry_and_text;
{
     GtkWidget *w;
     char *text;
};
void free_data(gpointer data, GClosure *closure)
{
     free(data);
}

entry_and_text *data = (entry_and_text *)malloc(sizeof(entry_and_text));
data->w = entry;
data->text = label;
g_signal_connect_data (button, "clicked",
          G_CALLBACK (callback), data, free_data, 0);

Upvotes: 1

Related Questions