如何将“clicked”信号和“key_press_event”连接到同一个回调函数?

时间:2013-04-14 04:01:50

标签: c gtk

我想要做的是将鼠标点击“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”没有做任何事情。任何帮助表示赞赏。

2 个答案:

答案 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 */
}

为了能够理解后一个例子,你必须知道:

  1. 如果不使用,则会丢弃返回值(如果您不想停止事件处理,必须从按键事件返回FALSE);
  2. 回调中的额外参数会被无声地丢弃。
  3. 这意味着当点击调用callback()时,您在事件中有数据值(NULL)按键事件已正确设置,数据会被静默丢弃。

    这反过来意味着如果你在第二个例子中添加event != NULL的支票,就会开始工作。