C:使用GTk+跟踪鼠标移动;
考虑以下代码:C:使用GTk+跟踪鼠标移动;,c,gtk,C,Gtk,考虑以下代码: #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;
#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: (380,44)
Coordinates: (380,44)
这基本上是说鼠标没有移动(它从(380,44)移动到(380,44)),那么怎么可能有移动事件来启动第二行输入的处理程序呢
另一个不太重要且(可能)不相关的问题:
为什么这条线是必要的
gtk_widget_set_events(main_window, GDK_POINTER_MOTION_MASK);
在GTK+发展的图书基础上,它说:
接下来,您需要向事件框添加事件掩码,以便它知道 小部件将接收什么类型的事件。价值观 表中显示了指定事件掩码的GDKEVENTMAK枚举 3-3. GDKEVENTMAK值的按位列表可以传递给 gtk_widget_set_events(),如果需要设置多个事件 但考虑到我们已经有了g_signal_connect(),这个调用不是多余的吗?也就是说,根据文件: 将GCallback函数连接到特定对象的信号 处理程序将在信号的默认处理程序之前调用 为什么我需要注册两次信号?一次是使用
gtk\u widget\u set\u events()
,第二次是使用g\u signal\u connect()
?我尝试直接使用xev监控X服务器中的鼠标移动,似乎xorg报告了具有相同坐标但不同时间戳的多个鼠标事件。然而,当使用键盘上的指向棒时,它并没有这样做,只有使用触控板或外部鼠标
我的猜测是,精度实际上更高,但事件是以屏幕上的一个像素为单位报告的。这可能会导致驱动程序报告更多需要的鼠标事件
为什么这条线是必要的
gtk_小部件设置_事件(主窗口、GDK_指针、运动)
MASK)
但考虑到我们已经有了g_signal_connect(),这个调用不是多余的吗?也就是说,根据文件:
例如,考虑一个例子。
如果单击,您将注意到有6个可用信号:
Signals
void activate Action
void clicked Action
void enter Run First
void leave Run First
void pressed Run First
void released Run First
它们中没有一个是来自的scroll\u 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-Down Detected
Scroll-Down Detected
Scroll-Down Detected
Scroll-UP Detected
Scroll-UP Detected
Scroll-UP Detected
这不是一个完整的答案,但是:
gtk\u小部件\u set\u events()
和g\u signal\u connect()
不是“为信号注册两次”。gtk\u widget\u set\u events()
调用是您请求接收GK事件,这些事件作为您使用g\u signal\u connect()连接的信号传递。然而,我不知道为什么必须明确要求GDK事件。(也可以考虑<代码> GtkWiWigGeDigAdGyAdvsId)(),这就避免了在默认情况下跟踪您所添加的事件的需要,作为对“代码> GTKKWIDGETSITS事件()/代码>的替代方案。)我也不确定,但我相信<代码> GTKYWIDGETSETSyEngEvsServer()的原因。
是由于性能原因,某些事件默认情况下不会发出。(如果没有人想要它们,那么你最好避免发射它们的性能开销,特别是如果它们像指针运动事件一样非常频繁。)@ptomato我认为你是对的。。。当我注释掉gtk\u widget\u set\u events()
时,我再也不会收到鼠标移动的通知了……这很有趣。。。我应该用一个外部鼠标测试它(因为这是一台笔记本电脑,我只在面板上的跟踪板上试过),然后我会报告。好的,我又试了一次,使用外部鼠标的频率似乎比笔记本电脑的跟踪板要低。是的。当我使用指针板时,上面的输出显示有很多重复项,但当我使用外部USB鼠标时,根本没有重复项。。。这可能是驱动程序相关的问题。。。谢谢你的帮助。
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