2

我想做的是将鼠标单击“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,当我点击按钮时,我得到 SegFault 指向s_up。按“s”没有任何作用。任何帮助表示赞赏。

4

2 回答 2

4

您不能将两个信号直接连接到同一个信号处理程序,因为它们需要不同的参数。

你得到一个分段错误的原因是因为event->keyval只有当你收到一个key-press-event. 当您收到clicked事件时,第二个参数将是NULL,因为它映射到事件gpointer提供的参数,clicked并且您已将其设置为NULL安装信号处理程序时,所以event将是NULL

如果您想要将两个信号连接到同一个处理程序的原因是您有公共代码,无论哪个信号触发它都应该运行,那么解决方案是为每个信号设置一个处理程序,并使用第三个函数使用公共代码他们可以打电话。

于 2013-04-14T05:58:42.117 回答
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在第二个示例中添加检查,事情就会开始工作。

于 2013-04-14T13:48:44.923 回答