【问题标题】:How do I get Keyboard and Mouse Input in GTK?如何在 GTK 中获得键盘和鼠标输入?
【发布时间】:2011-12-03 13:18:02
【问题描述】:

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

【问题讨论】:

  • 我认为 GTK 可能是这个工作的错误工具......听起来你应该看看游戏编程库。
  • @DeadMG 对不起标签。我想既然我提到了第三方 CC++ 库,应该包含 C++ 和 C 标签。
  • 如果你对这个项目不太了解,你可以看看 Qt。将其用作游戏引擎没有问题(据我所知)。

标签: c++ c input gtk


【解决方案1】:

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

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

你这是什么意思?我认为您正在描述键重复行为(与在文本编辑器中按住“a”并按住它时相同,您会得到“aaaaaaaaaaaaaa”。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 (); 

【讨论】:

  • 我的意思是键重复不一致,就像在 SFML 和 SDL 中一样。如果你在 SDL 中移动一个精灵,它会均匀移动,因为 isKeyPressed() 在你释放键之前总是评估为真。但是在 GTK+ 中,如果你按住一个键,精灵会移动,然后像一秒钟一样停止,然后再次移动,然后停止,然后移动......即 isKeyPressed() 评估为真,然后是假,然后是真。然后假一微秒,然后再次为真。我知道,抱歉很难解释。
【解决方案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/

【讨论】:

  • 嗯,你可能想提一下 gtkglext 只是 Gtk2。 Gtk2 不再维护,和/或 ApprenticeHacker 可能正在使用 Gtk3。 GtkGLArea 是当前维护的将 GL 与 Gtk 一起使用的方式。
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-09
    • 2021-09-21
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-22
    相关资源
    最近更新 更多