如何在GTKMM4中让Gtk::Viewport固定尺寸以实现滚动?
解决Gtk::Viewport无法滚动的问题
问题原因
你当前的布局中,Gtk::Box默认会强制子部件(Gtk::Viewport)填充可用空间,同时Gtk::Viewport会自适应内容(LargeWidget)的尺寸,导致它被拉伸至100x200,失去滚动触发条件。
可行解决方案
方案一:调整现有布局,限制Viewport尺寸
通过设置Viewport的尺寸请求,并禁止它在布局中自动扩展,同时修正滚动条的调整参数:
#include <gtkmm.h> class LargeWidget : public Gtk::DrawingArea { public: LargeWidget(int width, int height) { set_content_width(width); set_content_height(height); } }; class Window : public Gtk::Window { Gtk::Box box; Gtk::Scrollbar scrollbar; Glib::RefPtr<Gtk::Adjustment> v; Gtk::Viewport viewport; LargeWidget large_widget; public: Window() : v(Gtk::Adjustment::create(0, 0, 200, 1, 10, 10)), viewport(Gtk::Adjustment::create(0,0,100), v), large_widget(100, 200) { scrollbar.set_orientation(Gtk::Orientation::VERTICAL); scrollbar.set_adjustment(viewport.get_vadjustment()); viewport.set_child(large_widget); // 限制Viewport的尺寸请求,禁止垂直方向自动扩展 viewport.set_size_request(100, 100); viewport.set_vexpand(false); viewport.set_hexpand(true); // 水平方向填充窗口宽度(减去滚动条) box.set_orientation(Gtk::Orientation::HORIZONTAL); box.append(viewport); box.append(scrollbar); set_default_size(100, 100); set_child(box); } }; int main(int argc, char **argv) { auto app = Gtk::Application::create("hu.aszn.playground"); return app->make_window_and_run<Window>(argc, argv); }
方案二:使用Gtk::ScrolledWindow(推荐)
Gtk::ScrolledWindow已经封装了Viewport和滚动条的逻辑,无需手动组合,代码更简洁:
#include <gtkmm.h> class LargeWidget : public Gtk::DrawingArea { public: LargeWidget(int width, int height) { set_content_width(width); set_content_height(height); } }; class Window : public Gtk::Window { Gtk::ScrolledWindow scrolled_window; LargeWidget large_widget; public: Window() : large_widget(100, 200) { // 设置滚动条策略:垂直滚动条按需显示,水平滚动条永不显示 scrolled_window.set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::AUTOMATIC); scrolled_window.set_child(large_widget); set_default_size(100, 100); set_child(scrolled_window); } }; int main(int argc, char **argv) { auto app = Gtk::Application::create("hu.aszn.playground"); return app->make_window_and_run<Window>(argc, argv); }
关键说明
- 方案一中,
set_vexpand(false)阻止Viewport在垂直方向被Box拉伸,set_size_request固定其初始高度,当内容超出时,Adjustment会触发滚动。 - 方案二中,
Gtk::ScrolledWindow会自动根据内容和自身尺寸判断是否显示滚动条,无需手动管理Adjustment和滚动条的绑定。
内容的提问来源于stack exchange,提问作者mltm
相关产品推荐
相关产品推荐

