2013-04-14 21 views
3

我想要做的是連接鼠標點擊「點擊」信號與按鍵「key_press_event」信號相同的回調函數。代碼從這樣開始:如何將「clicked」信號和「key_press_event」連接到同一個回調函數?

static void s_up(GtkWidget *btn, 
       gpointer data) 
{ 
    code ... 
} 

... 

int main(int argc, char **argv) 
{ 
    ... 
    g_signal_connect(button, "clicked", G_CALLBACK(s_up), NULL); 
} 

它處理鼠標點擊就好了。然後,我想添加鍵盤按它。所以我將代碼更改爲

static void s_up(GtkWidget *btn, 
       GdkEventKey *event 
       gpointer data) 
{ 
    if(event->keyval == 's') 
     more code ... 
} 

... 

int main(int argc, char **argv) 
{ 
    ... 

    g_signal_connect(button, "key_press_event", G_CALLBACK(s_up), NULL); 
} 

當我按下鍵盤上的「s」時它就起作用了。

我的問題是如何將兩個信號連接到同一個s_up回調函數?除了其它if(event->keyval == 's')明顯的問題,我打過電話都gtk_signal_connect,當我點擊了按鈕,我得到段錯誤指向s_up。按「s」沒有做任何事情。任何幫助表示讚賞。

回答

2

使用包裝函數來間接調用相同的回調:

static void 
callback(GtkWidget *button, gpointer data) 
{ 
    /* TODO */ 
} 

static gboolean 
wrapper(GtkWidget *button, GdkEventKey *event, gpointer data) 
{ 
    if (event->keyval == 's') 
     callback(button, data); 
    return FALSE; 
} 

int 
main(int argc, char **argv) 
{ 
    /* TODO */ 
    g_signal_connect(button, "clicked", G_CALLBACK(callback), NULL); 
    g_signal_connect(button, "key-press-event", G_CALLBACK(wrapper), NULL); 
    /* TODO */ 
} 

如果你不使用data你也可以使用一個單一的功能,但在我看來,帶來的複雜性是不值得的努力:

static gboolean 
callback(GtkWidget *button, GdkEventKey *event) 
{ 
    if (event != NULL && event->keyval == 's') 
     callback(button, data); 
    return FALSE; 
} 

int 
main(int argc, char **argv) 
{ 
    /* TODO */ 
    g_signal_connect(button, "clicked", G_CALLBACK(callback), NULL); 
    g_signal_connect(button, "key-press-event", G_CALLBACK(callback), NULL); 
    /* TODO */ 
} 

爲了能夠理解你必須知道後者的例子:

  1. 如果沒有使用的返回值被丟棄(你必須回報FALSE從,如果你不想停止事件處理按鍵事件);
  2. 在回調中多餘的參數被丟棄。

這意味着當callback()是由一種叫做點擊你有數據值(NULL)在事件而當它被從按鍵的事件的設置正確,數據是叫默默丟棄。

這也就意味着,如果你在第二個例子中添加東西的支票event != NULL開始工作。

4

您不能同時將信號直接傳送,因爲它們需要不同的參數連接到相同的信號處理程序。

爲什麼你分割故障是因爲當你收到一個key-press-eventevent->keyval纔有意義的原因。當您收到clicked事件的第二個參數將是NULL,因爲其映射到與clicked事件提供的gpointer說法,你已經設置,當你安裝了信號處理NULL,所以eventNULL

如果你想將兩個信號連接到同一個處理程序的原因是你有通用的代碼,無論哪個信號觸發它,那麼解決方案是每個信號有一個處理程序,第三個函數它們都可以調用的通用代碼。

+0

我會補充說''gtk_signal_connect'已經過時多年了,他應該使用'g_signal_connect'來代替。 – liberforce

+0

對不起,我確實使用'g_signal_connect',輸入錯了。 – lllluuukke