簡體   English   中英

C:使用GTk +跟蹤鼠標移動

[英]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_eventGdkEventScroll ,這意味着下面的程序不一樣(可能)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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM