2012-04-23 121 views
1
#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; 
} 

這是什麼問題?
我沒有錯誤,沒有警告,但在終端上,該程序不能寫什麼:(
如果我寫:
gtk回調多個參數

test.host="trying something" 

它的工作原理但gtk_entry_get_text它並沒有顯示什麼:(
我不明白...爲什麼它不適用於gtk_entry_get_text?

+0

這是真的,你不能在C中做到這一點。這個問題已經在這裏解答:http://stackoverflow.com/questions/6684466/c-passing-multiple-arguments-to-a-callback-function- in-gtk – ptomato 2012-04-23 11:40:17

+0

好的謝謝...所以我必須使用typedef結構?這是更好的方法? – polslinux 2012-04-23 12:01:16

+1

是的,如果你有多個值傳遞給你的回調函數,那麼使用指向struct的指針作爲g_signal_connect的最後一個參數。您回調的原型必須始終遵循相應信號的原型。這裏是「[clicked]」(http://developer.gnome.org/gtk3/stable/GtkButton.html#GtkButton-clicked)「信號。 – liberforce 2012-04-23 12:24:58

回答

3

你需要明白,GTK是一個事件驅動的工具包(就像其他很多),你需要與事件交互,但它贏得了'在你運行gtk_main之前檢查事件,所以你的問題是你正在使用主機名test.host = gtk_entry_get_text(GTK_ENTRY (h_name)),但那時候,小部件還沒有顯示出來,甚至沒有輸入任何東西!所以你基本上只是從中得到一個空字符串,這就是你點擊「連接」按鈕時顯示的內容。

做到這一點的一種方法是將指針指向結構中的小部件。這樣,您可以從b_clicked回調中調用gtk_entry_get_text。這樣,您獲得的價值就是那個文本條目窗口小部件當時的價格

#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; 
} 

另一種更好的方式來做到這一點,不修改你的結構,是要求在文本發生變化時得到通知。爲此,請使用「changed」信號,因爲GtkEntry實現了GtkEditable接口。參見「GtkEntry text change signal」。

請注意,(gpointer*)&test是錯誤的。測試是一個結構,&測試是結構的地址。 gpointer是一個void *,即。已經是一個指針了,所以gpointer *是一個指向指針的指針,這不是&測試的結果。所以只需寫&test

+0

非常感謝,你是非常徹底!:) – polslinux 2012-04-23 13:41:01

+0

現在,如果我更徹底地研究信號和事件:)再次,謝謝:) – polslinux 2012-04-23 13:43:06