为何GdkEventKey未被声明?gtkmm4键盘事件代码报错排查
gtkmm-4.0键盘事件代码编译错误原因及修复
问题描述
从旧版GTK文档学习键盘事件,编写基于gtkmm-4.0的代码时编译报错,提示GdkEventKey未声明、Gtk::Box无signal_key_press_event成员等错误。
报错信息
/home/test/Desktop/not_working/main.cpp:15:52: error: ‘GdkEventKey’ has not been declared 15 | bool on_key_press_or_release_event(GdkEventKey * event){ | ^~~~~~~~~~~ /home/test/Desktop/not_working/main.cpp: In constructor ‘App::App()’: /home/test/Desktop/not_working/main.cpp:13:13: error: ‘class Gtk::Box’ has no member named ‘signal_key_press_event’ 13 | box.signal_key_press_event().connect(sigc::mem_fun(*this, &App::on_key_press_or_release_event)); | ^~~~~~~~~~~~~~~~~~~~~~ /home/test/Desktop/not_working/main.cpp: In member function ‘bool App::on_key_press_or_release_event(int*)’: /home/test/Desktop/not_working/main.cpp:16:38: error: request for member ‘type’ in ‘* event’, which is of non-class type ‘int’ 16 | if (event->type == GDK_KEY_PRESS && event->keyval == GDK_KEY_Return) | ^~~~ /home/test/Desktop/not_working/main.cpp:16:70: error: request for member ‘keyval’ in ‘* event’, which is of non-class type ‘int’ 16 | if (event->type == GDK_KEY_PRESS && event->keyval == GDK_KEY_Return) |
原代码(main.cpp)
#include <gtkmm.h> #include <stdio.h> class App: public Gtk::Window{ protected: Gtk::Box box; Gtk::Text text; public: App(){ set_child(box); box.append(text); text.set_text("hello world"); //box.signal_key_press_event().connect( sigc::ptr_fun(&on_key_press_or_release_event) ); } bool on_key_press_or_release_event(GdkEventKey * event){ if (event->type == GDK_KEY_PRESS && event->keyval == GDK_KEY_Return) { printf("Hello there"); return true; } return false; } }; int main(int argc, char * argv[]) { auto app = Gtk::Application::create("org.example.github.basic"); app->make_window_and_run<App>(argc, argv); return 0; }
CMake配置
cmake_minimum_required(VERSION 3.0) project(example) find_package(PkgConfig) pkg_check_modules(GTKMM REQUIRED gtkmm-4.0) add_executable(app main.cpp) target_include_directories(app PRIVATE ${GTKMM_INCLUDE_DIRS}) target_compile_options(app PRIVATE ${GTKMM_CFLAGS_OTHER}) target_link_libraries(app PRIVATE ${GTKMM_LIBRARIES})
错误原因
- 事件系统重构:gtkmm-4.0(对应GTK4)彻底抛弃了旧版的
signal_key_press_event这类底层事件信号接口,改用Gtk::EventController系列类处理输入事件,因此Gtk::Box不再具备signal_key_press_event成员。 - 旧类型废弃:
GdkEventKey这类C风格事件结构体在GTK4中已被移除,替换为面向对象的Gdk::KeyEvent类;同时旧的宏如GDK_KEY_PRESS、GDK_KEY_Return也被替换成Gdk::EventType::KEY_PRESS和Gdk::Key::Return枚举值。 - 焦点问题:即使在旧版GTK中,
Gtk::Box作为容器默认不获取键盘焦点,无法接收键盘事件,需要让可聚焦控件(如Gtk::Text)处理事件,而gtkmm4中统一通过事件控制器绑定到目标控件。
修复后的代码示例
#include <gtkmm.h> #include <iostream> class App: public Gtk::Window{ protected: Gtk::Box box; Gtk::Text text; // 声明键盘事件控制器 Glib::RefPtr<Gtk::EventControllerKey> key_controller; public: App(){ set_child(box); box.append(text); text.set_text("hello world"); text.set_hexpand(true); text.set_vexpand(true); // 创建键盘事件控制器并绑定到Text控件 key_controller = Gtk::EventControllerKey::create(); key_controller->signal_key_pressed().connect( sigc::mem_fun(*this, &App::on_key_pressed), false); text.add_controller(key_controller); } // 新的事件处理函数签名,适配GTK4规范 bool on_key_pressed(guint keyval, guint keycode, Gdk::ModifierType state){ if(keyval == Gdk::Key::Return){ std::cout << "Hello there" << std::endl; return true; } return false; } }; int main(int argc, char * argv[]) { auto app = Gtk::Application::create("org.example.github.basic"); return app->make_window_and_run<App>(argc, argv); }
说明
修复后的代码使用Gtk::EventControllerKey处理键盘按下事件,绑定到可聚焦的Gtk::Text控件(确保能接收键盘输入),事件处理函数采用GTK4的枚举值和新参数签名,完全符合gtkmm4的API规范。
内容的提问来源于stack exchange,提问作者misha
相关产品推荐
相关产品推荐

