2
votes
#include <gtk/gtk.h>
#include <stdio.h>

typedef struct {
    const gchar *host;
} example;

void b_clicked (GtkButton *c_button, example *test){
    g_print("Hostname: %s\n", test->host);
}

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

GtkWidget *window;
GtkWidget *grid;
GtkWidget *c_button;
GtkWidget *q_button;
GtkWidget *label_host;
GtkWidget *h_name;

gtk_init (&argc, &argv);

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "FTP Client");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
gtk_grid_set_row_spacing (GTK_GRID (grid), 3);

label_host = gtk_label_new("Hostname");

example test;
h_name = gtk_entry_new();
test.host = gtk_entry_get_text(GTK_ENTRY (h_name));
gtk_entry_set_placeholder_text (GTK_ENTRY (h_name), "Hostname");
c_button = gtk_button_new_with_label ("Connect");
g_signal_connect (c_button, "clicked", G_CALLBACK (b_clicked), (gpointer*)&test);
q_button = gtk_button_new_with_label ("Quit");
g_signal_connect (q_button, "clicked", G_CALLBACK (gtk_main_quit), NULL);

gtk_grid_attach (GTK_GRID (grid), label_host, 0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid), h_name, 1, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid), c_button, 0, 3, 2, 1);
gtk_grid_attach (GTK_GRID (grid), q_button, 0, 4, 2, 1);

gtk_widget_show_all (window);

gtk_main ();

return 0;
}

What is wrong whit this??
i have no errors and no warnings but on the terminal this program doesn't write anything :(
if i write:

test.host="trying something"

it works but with gtk_entry_get_text it doesn't show nothing :(
i don't understand...why it doesn't work with gtk_entry_get_text?

1
It's true, you can't do this in C. This question is already answered here: stackoverflow.com/questions/6684466/…ptomato
ok thanks...so i have to use typedef struct?? It is the better way??polslinux
Yeah, use a pointer to a struct as the last parameter of g_signal_connect if you have multiple values to pass to your callback. You callback's prototype must always follow the one for the corresponding signal. Here is the one for the "clicked" signal.liberforce
i have updated my code..could you please checking what is wrong?? :( thankspolslinux

1 Answers

4
votes

You need to understand that GTK is an event-driven toolkit (like many other). You need interact with events. But it won't check for events until you've run gtk_main. So your problem is that you're reading the hostname using test.host = gtk_entry_get_text(GTK_ENTRY (h_name)), but at that time, the widget hasn't been displayed, and you didn't even typed anything in it! So you're basically just getting a null string from this, and that is what you display when you click on the "connect" button.

One way to do it is to have your pointer to widgets in the struct. That way, you call gtk_entry_get_text from inside the b_clicked callback. That way, the value you get is the one that is inside the text entry widget at that time.

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

typedef struct {
        GtkWidget *host;
} example;

void b_clicked (GtkButton *c_button, example *test){
        g_print("Hostname: %s\n", gtk_entry_get_text (GTK_ENTRY(test->host)));
}

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

        GtkWidget *window;
        GtkWidget *grid;
        GtkWidget *c_button;
        GtkWidget *q_button;
        GtkWidget *label_host;
        GtkWidget *h_name;

        gtk_init (&argc, &argv);

        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title (GTK_WINDOW (window), "FTP Client");
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
        g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
        gtk_container_set_border_width (GTK_CONTAINER (window), 10);
        gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

        grid = gtk_grid_new ();
        gtk_container_add (GTK_CONTAINER (window), grid);
        gtk_grid_set_row_spacing (GTK_GRID (grid), 3);

        label_host = gtk_label_new("Hostname");

        example test;
        h_name = gtk_entry_new();
        test.host = h_name;
        gtk_entry_set_placeholder_text (GTK_ENTRY (h_name), "Hostname");
        c_button = gtk_button_new_with_label ("Connect");
        g_signal_connect (c_button, "clicked", G_CALLBACK (b_clicked), &test);
        q_button = gtk_button_new_with_label ("Quit");
        g_signal_connect (q_button, "clicked", G_CALLBACK (gtk_main_quit), NULL);

        gtk_grid_attach (GTK_GRID (grid), label_host, 0, 0, 1, 1);
        gtk_grid_attach (GTK_GRID (grid), h_name, 1, 0, 1, 1);
        gtk_grid_attach (GTK_GRID (grid), c_button, 0, 3, 2, 1);
        gtk_grid_attach (GTK_GRID (grid), q_button, 0, 4, 2, 1);

        gtk_widget_show_all (window);

        gtk_main ();

        return 0;
}

Another nicer way to do it is, without modifying your struct, is to ask to be notified when the text has changed. For that, use the "changed" signal, as GtkEntry implements the GtkEditable interface. See "GtkEntry text change signal".

Please also note that (gpointer*)&test is wrong. test is a struct, &test is the adress of a struct. gpointer is a void *, ie. already a pointer, so gpointer * is a pointer to a pointer, which is not what &test is. So just write &test.