我想要做的是将鼠标点击“clicked”信号和keypress“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
,当我点击按钮时,我让SegFault指向s_up
。按“s”没有做任何事情。任何帮助表示赞赏。
答案 0 :(得分:4)
您无法将两个信号直接连接到同一个信号处理程序,因为它们需要不同的参数。
您遇到细分错误的原因是因为event->keyval
仅在您收到key-press-event
时才有意义。当您收到clicked
事件时,第二个参数将为NULL
,因为它映射到gpointer
事件提供的clicked
参数,并且您已将其设置为{{1}当您安装信号处理程序时,NULL
将为event
。
如果你想将两个信号连接到同一个处理程序的原因是你有共同的代码应该运行,无论哪个信号触发它,那么解决方案是每个信号有一个处理程序和第三个共同的函数两个人都可以打电话的代码。
答案 1 :(得分: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 */
}
为了能够理解后一个例子,你必须知道:
FALSE
); 这意味着当点击调用callback()
时,您在事件中有数据值(NULL
)按键事件已正确设置,数据会被静默丢弃。
这反过来意味着如果你在第二个例子中添加event != NULL
的支票,就会开始工作。