gtk-rs:如何监听键盘事件

问题描述 投票:0回答:2

我正在使用

gtk-rs
并且希望能够检测何时按下任意键。

根据网上的一些搜索,似乎在 C 中执行此操作的方法是先使用

gtk_widget_add_events
,然后使用
g_signal_connect
这个答案有很好的解释。

在 Rust 中,我可以调用

Widget::add_events
。我还找到了
g_signal_connect_*
的几个定义。但是,这些函数
unsafe
,没有文档记录,并且似乎采用 C 类型作为参数。

我的问题是:

  1. 为了使用
    gobject_sys::g_signal_connect_closure
    ,如何创建
    GObject
    GClosure
    。在铁锈中? Rust 结构和闭包可以转换成那个吗?
  2. 有没有更好、更惯用的方式来监听关键事件?我很难相信做这样一个基本的事情会需要这样一个深奥的界面。我已经看到了对特定键盘快捷键或键盘加速组的一些支持,但我无法找到任何仅侦听按键事件的文档或示例。
rust gtk3 gtk-rs
2个回答
1
投票

我明白了。

谢谢@Jmb,

Widget::connect
是正确的选择。但是,该函数没有文档记录,并且有一些非常奇怪的类型。以下是我如何使用它的方法:

window
    .connect("key_press_event", false, |values| {
        // "values" is a 2-long slice of glib::value::Value, which wrap G-types
        // You can unwrap them if you know what type they are going to be ahead of time
        // values[0] is the window and values[1] is the event
        let raw_event = &values[1].get::<gdk::Event>().unwrap().unwrap();
        // You have to cast to the correct event type to access some of the fields
        match raw_event.downcast_ref::<gdk::EventKey>() {
            Some(event) => {
                println!("key value: {:?}", std::char::from_u32(event.get_keyval()));
                println!("modifiers: {:?}", event.get_state());
            },
            None => {},
        }

        // You need to return Some() of a glib Value wrapping a bool
        let result = glib::value::Value::from_type(glib::types::Type::Bool);
        // I can't figure out how to actually set the value of result
        // Luckally returning false is good enough for now.
        Some(result)
    })
    .unwrap();

0
投票

在寻找同一问题的解决方案时发现了这个问题,但无法像这个答案那样工作。

然后我找到了另一种实现按键事件处理程序的方法:

EventControllerKey
,您可以在其上连接到
key-pressed
key-released
modifiers
信号。然后你只需在窗口上注册 EventControllerKey 即可。

最小示例:

// ... Application setup

let window = gtk::ApplicationWindow::builder()
    .application(app)
    .build();

let event_controller = gtk::EventControllerKey::new();

event_controller.connect_key_pressed(|_, key, _, _| {
    match key {
        gdk::Key::Escape => {
            std::process::exit(0);
        }
        _ => (),
    }
    glib::Propagation::Proceed
});

window.add_controller(event_controller);
window.present();

我将其与

gtk4
一起使用。 希望有人觉得这很有用。

© www.soinside.com 2019 - 2024. All rights reserved.