You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 01:15:37