如何在GTK中获得键盘和鼠标输入?

时间:2011-10-08 12:36:50

标签: c++ c input gtk

我想在GTK +中接收键盘和鼠标输入。对于键盘输入,我尝试使用accelgroup,但它不像SDL或SFML那样流畅。当我按下一把钥匙。它响应,暂停一段时间,再次响应,暂停一段时间等等。通过鼠标输入我的意思是在给定时间获取鼠标的位置以及是否单击鼠标按钮。通过键盘输入我想跟踪按键和释放。我正在使用GTK +和cairo进行教育图形计划。有点像海龟图形。任何帮助?或者任何与GTK +配合使用并跟踪键盘和鼠标输入的第三方库(C或C ++)?

3 个答案:

答案 0 :(得分:2)

你想要做的是中等复杂。看看

http://developer.gnome.org/gtk-tutorial/2.90/

,特别是

http://developer.gnome.org/gtk-tutorial/2.90/x344.html

http://developer.gnome.org/gtk-tutorial/2.90/c2422.html

第二个链接包含键盘回调的源代码,似乎可以执行您想要的操作。第三个链接是使用鼠标的简单绘图程序教程的开始。

编辑:为了完整起见,我会提到gtkglext库支持在GTK +中使用OpenGL。参见

http://projects.gnome.org/gtkglext/

答案 1 :(得分:0)

根据文档] 1,你可以获得鼠标动作事件,为它们设置GDK_POINTER_MOTION_MASK的面具 - 这意味着即使没有按下任何按钮,你也会得到动作事件。此外,Gtk+ tutorials显示了一些利用鼠标运动事件的概念。

  

当我按下一个键时。它响应,暂停一段时间,再次响应,暂停一段时间等等。

这是什么意思?我想你正在描述关键的重复行为(当你按下'a'并按住它时,就像在文本编辑器中一样,你得到'aaaaaaaaaaaa'。To disable it in your app

XKeyboardControl control; 
control.auto_repeat_mode = 0; 

gdk_error_trap_push (); 
XChangeKeyboardControl (GDK_DISPLAY (), KBAutoRepeatMode, &control); 
gdk_error_trap_pop (); 

答案 2 :(得分:0)

这是一个示例代码示例,演示如何使用回调来注册鼠标移动和按键:

// compile with: gcc example.c `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0`
#include <stdio.h>
#include <gtk/gtk.h>

static gboolean is_w_pressed = FALSE;
static gboolean is_a_pressed = FALSE;
static gboolean is_s_pressed = FALSE;
static gboolean is_d_pressed = FALSE;
static gboolean is_q_pressed = FALSE;
static gboolean is_e_pressed = FALSE;

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);
    }
}

static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
    if (event->keyval == GDK_KEY_w)
    {
        is_w_pressed = TRUE;
        return TRUE;
    }
    else if (event->keyval == GDK_KEY_a)
    {
        is_a_pressed = TRUE;
        return TRUE;
    }
    else if (event->keyval == GDK_KEY_s)
    {
        is_s_pressed = TRUE;
        return TRUE;
    }
    else if (event->keyval == GDK_KEY_d)
    {
        is_d_pressed = TRUE;
        return TRUE;
    }
    return FALSE;
}

static gboolean key_released(GtkWidget *widget, GdkEventKey *event)
{
    if (event->keyval == GDK_KEY_w) {
        is_w_pressed = FALSE;
    }
    if (event->keyval == GDK_KEY_a) {
        is_a_pressed = FALSE;
    }
    if (event->keyval == GDK_KEY_s) {
        is_s_pressed = FALSE;
    }
    if (event->keyval == GDK_KEY_d) {
        is_d_pressed = FALSE;
    }
    return GDK_EVENT_PROPAGATE;
}

gboolean update (GtkWidget *widget, GdkFrameClock *clock, gpointer data)
{
    if (is_w_pressed) {
        printf("W key pressed!\n");
    }
    if (is_a_pressed) {
        printf("A key pressed!\n");
    }
    if (is_s_pressed) {
        printf("S key pressed!\n");
    }
    if (is_d_pressed) {
        printf("D key pressed!\n");
    }
    printf("updating...\n");
}

int main(int argc, char *argv[]) {
    GtkWidget *window;
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_events(window, GDK_KEY_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_POINTER_MOTION_MASK);
    gtk_widget_set_size_request(window, 320, 240);
    g_signal_connect(G_OBJECT(window), "motion-notify-event", G_CALLBACK(mouse_moved), NULL);
    g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(key_pressed), NULL);
    g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(key_released), NULL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_add_tick_callback(window, update, NULL, NULL);
    gtk_widget_show_all(window);
    gtk_main(); 
    return 0;
}