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

gtkmm 4中移动子类化Gtk::Window遇编译错误,求解决方案

解决Gtk4中窗口移动及获取显示器尺寸的问题

首先,你的代码遇到两个核心问题:Gdk::Monitor的类型错误和Gtk4中move()方法的移除,下面逐个帮你解决:

1. 修复显示器尺寸获取的错误

你用Glib::RefPtr<Glib::ObjectBase>存储显示器对象,但Glib::ObjectBase并没有get_rectangle()方法。正确的做法是直接获取Gdk::Monitor类型的对象——因为get_monitors()返回的是Glib::ListHandle<Gdk::Monitor>,可以直接通过索引拿到目标显示器:

// 正确获取第一个显示器的方式
Glib::RefPtr<Gdk::Monitor> first_monitor = Gdk::Display::get_default()->get_monitors()[0];
Gdk::Rectangle rect;
first_monitor->get_rectangle(rect);

这样就能正常调用get_rectangle()获取屏幕尺寸了。

2. 替代Gtk4中移除的move()方法

确实,Gtk4里Gtk::Window的move()方法被移除了。要实现窗口移动到指定位置,你需要先获取窗口对应的Gdk::Surface,然后调用Gdk::Surface::move()方法:

// 获取窗口的Gdk::Surface
Glib::RefPtr<Gdk::Surface> surface = this->get_surface();
if (surface) {
    int posx = (rect.get_width() - this->get_width()) / 2;
    int posy = (rect.get_height() - this->get_height()) / 2; // 你之前写的-1应该是笔误,改成居中y坐标更合理
    surface->move(posx, posy);
}

注意:必须确保窗口已经完成初始化(也就是调用realize()或者show()之后),否则get_surface()会返回空指针。如果在构造函数里调用,最好先执行this->realize()来确保surface存在。

修正后的完整代码

综合以上两点,你的构造函数可以修改为:

PrefsWindow::PrefsWindow() {
    this->set_title(_("Screenshot"));

    // 获取第一个显示器的尺寸
    Glib::RefPtr<Gdk::Monitor> first_monitor = Gdk::Display::get_default()->get_monitors()[0];
    Gdk::Rectangle rect;
    first_monitor->get_rectangle(rect);

    // 确保窗口初始化surface
    this->realize();
    Glib::RefPtr<Gdk::Surface> surface = this->get_surface();
    if (surface) {
        // 计算居中位置
        int posx = (rect.get_width() - this->get_width()) / 2;
        int posy = (rect.get_height() - this->get_height()) / 2;
        surface->move(posx, posy);
    }

    this->show();
}

额外小技巧

如果你只是想让窗口居中显示,Gtk4提供了更简便的方法,完全不用手动计算位置:

this->set_position(Gtk::WindowPosition::CENTER);

这个方法会自动让窗口在当前显示器居中,代码更简洁。

内容的提问来源于stack exchange,提问作者TheEagle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:15:30