【发布时间】:2015-03-16 17:37:15
【问题描述】:
考虑以下代码:
#include<gtk/gtk.h>
#include<stdio.h>
static void destroy(GtkWidget*, gpointer);
static gboolean mouse_moved(GtkWidget *widget,GdkEvent *event,gpointer user_data);
int main(int argc, char* argv[]) {
GtkWidget *main_window;
// initializing
gtk_init(&argc, &argv);
main_window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(main_window),"Test");
gtk_widget_set_size_request (main_window, 500, 300);
// connect the window with signals
g_signal_connect (G_OBJECT (main_window), "destroy",G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (main_window), "motion-notify-event",G_CALLBACK (mouse_moved), NULL);
gtk_widget_set_events(main_window, GDK_POINTER_MOTION_MASK);
// show window
gtk_widget_show_all (main_window);
gtk_main();
return 0;
}
static void destroy(GtkWidget *window,gpointer data) {
gtk_main_quit ();
}
static gboolean mouse_moved(GtkWidget *widget,GdkEvent *event, gpointer user_data) {
if (event->type==GDK_MOTION_NOTIFY) {
GdkEventMotion* e=(GdkEventMotion*)event;
printf("Coordinates: (%u,%u)\n", (guint)e->x,(guint)e->y);
}
}
当我从终端运行此代码时,它会打开一个空窗口,并每次打印出鼠标坐标。
这是上次执行的(部分)输出:
Coordinates: (390,17)
Coordinates: (390,18)
Coordinates: (390,18)
Coordinates: (390,18)
Coordinates: (390,18)
Coordinates: (390,19)
Coordinates: (390,19)
Coordinates: (390,19)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,22)
Coordinates: (391,23)
Coordinates: (391,23)
Coordinates: (391,23)
Coordinates: (390,23)
Coordinates: (390,23)
Coordinates: (390,23)
Coordinates: (390,23)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,24)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,25)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,26)
Coordinates: (390,27)
Coordinates: (390,27)
Coordinates: (390,27)
Coordinates: (390,27)
Coordinates: (390,27)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,28)
Coordinates: (390,29)
Coordinates: (390,29)
Coordinates: (390,29)
Coordinates: (390,30)
Coordinates: (390,30)
Coordinates: (390,30)
Coordinates: (390,30)
Coordinates: (390,31)
Coordinates: (390,31)
Coordinates: (390,32)
Coordinates: (390,32)
Coordinates: (390,32)
Coordinates: (390,33)
Coordinates: (390,33)
Coordinates: (390,33)
Coordinates: (390,33)
Coordinates: (390,33)
Coordinates: (390,34)
Coordinates: (390,34)
Coordinates: (390,34)
Coordinates: (389,34)
Coordinates: (389,35)
Coordinates: (389,36)
Coordinates: (389,36)
Coordinates: (389,36)
Coordinates: (389,37)
Coordinates: (389,36)
Coordinates: (389,37)
Coordinates: (389,37)
Coordinates: (389,37)
Coordinates: (389,37)
Coordinates: (389,38)
Coordinates: (389,38)
Coordinates: (388,38)
Coordinates: (388,38)
Coordinates: (388,38)
Coordinates: (388,38)
Coordinates: (388,39)
Coordinates: (388,39)
Coordinates: (388,39)
Coordinates: (388,39)
Coordinates: (388,39)
Coordinates: (388,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (387,40)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (386,41)
Coordinates: (385,41)
Coordinates: (385,41)
Coordinates: (385,41)
Coordinates: (385,41)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (384,42)
Coordinates: (383,42)
Coordinates: (383,42)
Coordinates: (383,42)
Coordinates: (383,42)
Coordinates: (383,43)
Coordinates: (382,43)
Coordinates: (382,43)
Coordinates: (382,43)
Coordinates: (382,43)
Coordinates: (381,43)
Coordinates: (381,43)
Coordinates: (381,43)
Coordinates: (380,43)
Coordinates: (380,44)
Coordinates: (380,44)
Coordinates: (380,44)
Coordinates: (380,44)
Coordinates: (379,44)
Coordinates: (378,44)
Coordinates: (378,44)
Coordinates: (377,44)
Coordinates: (377,44)
等等……
让我困惑的是:怎么会有两个连续的事件拥有相同的坐标?例如,采取以下两行:
Coordinates: (380,44)
Coordinates: (380,44)
这基本上是说鼠标没有移动(它从 (380,44) 变为 (380,44)),所以怎么可能有一个移动事件来启动第二行输入的处理程序?
另一个不太重要且(也许)不相关的问题:
为什么这条线是必要的?
gtk_widget_set_events(main_window, GDK_POINTER_MOTION_MASK);
在 Gtk+ 开发基础一书中说:
接下来,你需要给事件框添加一个事件掩码,让它知道 小部件将接收什么类型的事件。的值 指定事件掩码的 GdkEventMask 枚举如表所示 3-3。可以将 GdkEventMask 值的按位列表传递给 gtk_widget_set_events() 如果你需要设置多个。
但是考虑到我们已经有了 g_signal_connect(),这个调用不是多余的吗?也就是说,根据文档:
将 GCallback 函数连接到特定对象的信号。
处理程序将在信号的默认处理程序之前调用。
为什么我需要注册两次信号?
一次使用gtk_widget_set_events(),第二次使用g_signal_connect()?
【问题讨论】:
-
不是一个完整的答案,但是:
gtk_widget_set_events()和g_signal_connect()不是“两次注册信号”。gtk_widget_set_events()呼叫是您要求接收 GK 事件,这些事件作为您与g_signal_connect()连接的信号传递。 为什么您必须明确要求 GDK 事件,但是,我不知道。 (您也可以考虑使用gtk_widget_add_events(),这样就无需知道默认情况下会收到哪些事件/跟踪您添加的事件,作为gtk_widget_set_events()的替代方案。) -
我也不确定,但我相信
gtk_widget_set_events()的原因是出于性能原因默认不发出某些事件。 (如果没有人想要它们,那么您最好避免发出它们的性能开销,特别是如果它们像指针运动事件一样非常频繁。) -
@ptomato 我认为你是对的...当我注释掉
gtk_widget_set_events()时,我不再收到有关鼠标移动的通知...