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
相关产品推荐
相关产品推荐

