请考虑以下代码:
#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()
?
答案 0 :(得分:3)
我尝试使用xev直接监视X服务器中的鼠标移动,似乎xorg报告具有相同坐标但不同时间戳的多个鼠标事件。使用键盘上的指点杆但是它没有这样做,只能使用触控板或外接鼠标。
我的猜测是精度实际上更高,但会报告屏幕上像素的事件。这可能会导致驱动程序报告所需的更多鼠标事件。
答案 1 :(得分:0)
为什么需要此行?
gtk_widget_set_events(main_window, GDK_POINTER_MOTION_
蒙版);
但是,鉴于我们已经有了g_signal_connect(),因此此调用是否多余?根据文档:
例如,考虑一个GtkButton like this one。 如果您点击Signals Link,则会注意到有6种信号可用:
Signals
void activate Action
void clicked Action
void enter Run First
void leave Run First
void pressed Run First
void released Run First
它们都不是GdkEventScroll中的scroll_event
,这意味着以下程序无法(可能)正常工作:
#include <gtk/gtk.h>
gboolean scroll_callback ( GtkWidget *widget, GdkEvent *event, gpointer user_data );
int main ( void )
{
GtkWidget *window;
GtkWidget *button;
gtk_init( NULL, NULL );
/// ***
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_window_set_default_size( GTK_WINDOW( window ), 300, 250 );
g_signal_connect( window, "destroy", gtk_main_quit, NULL );
gtk_container_set_border_width( GTK_CONTAINER( window ), 25 );
/// ***
button = gtk_button_new_with_mnemonic( "_Click me" );
g_signal_connect( button, "clicked", gtk_main_quit, NULL );
gtk_container_add( GTK_CONTAINER( window ), button );
/// ***
g_signal_connect( button, "scroll_event", G_CALLBACK( scroll_callback ), window );
/// ***
gtk_widget_show_all( window );
gtk_main();
}
gboolean scroll_callback ( GtkWidget *widget, GdkEvent *event, gpointer data )
{
(void)widget;
if ( event->type == GDK_SCROLL ) /// Scroll the was Catched
{
if ( event->scroll.direction == GDK_SCROLL_DOWN )
{
g_print( "Scroll-Down Detected\n" );
gtk_window_set_title( GTK_WINDOW( data ), "Scroll-Down Detected" );
}
if ( event->scroll.direction == GDK_SCROLL_UP )
{
g_print( "Scroll-UP Detected\n" );
gtk_window_set_title( GTK_WINDOW( data ), "Scroll-UP Detected" );
}
return FALSE;
}
return TRUE;
}
在这里,我们尝试捕获scroll_event
信号事件,但是它本身的小部件(按钮)没有这种类型的信号。
要修复它,我们在创建按钮后立即将事件设置/添加到按钮:
button = gtk_button_new_with_mnemonic( "_Click me" );
gtk_widget_set_events( button, GDK_SCROLL_MASK );
程序运行正常:
Scroll-Down Detected
Scroll-Down Detected
Scroll-Down Detected
Scroll-UP Detected
Scroll-UP Detected
Scroll-UP Detected