[英]C: Tracking mouse movement with 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;
// 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()
?
我嘗試使用xev直接監視X服務器中的鼠標移動,似乎xorg報告具有相同坐標但不同時間戳的多個鼠標事件。 使用鍵盤上的指點桿時,它不會這樣做,只能使用觸控板或外接鼠標。
我的猜測是精度實際上更高,但是報告屏幕上的像素的事件。 這可能會導致驅動程序報告所需的更多鼠標事件。
為什么這條線是必要的?
gtk_widget_set_events(main_window, GDK_POINTER_MOTION_
MASK);
但鑒於我們已經擁有g_signal_connect(),這個調用不是多余的嗎? 根據文件,這是:
想想像這樣的GtkButton 。 如果您點擊信號鏈接,您會注意到有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_event
從GdkEventScroll ,這意味着下面的程序不一樣(可能)espected工作:
#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
信號事件,但它自己的widget(按鈕)沒有這種類型的Signal。
要修復它,我們在創建它之后設置/添加事件到按鈕:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.