【发布时间】:2020-04-10 14:06:07
【问题描述】:
我正在使用 Gtkmm3 (Ubuntu) 制作一个小型 GUI 应用程序。在这个应用程序中,我有几个窗口要创建,它们基本上都遵循相同的模式:
- 注册主布局 (
Gtk::Grid); - 配置窗口属性(图标、标题等);
- 配置布局属性(扩展、子布局等);
- 配置窗口小部件(将它们添加到布局、标签等)。
希望每次创建新窗口时不必重写所有这些逻辑,我编写了以下基类:
template<typename GtkmmWindow>
class Window
{
public:
Window();
virtual int Show() = 0;
protected:
virtual void ConfigureWindow() = 0;
virtual void ConfigureLayouts() = 0;
virtual void ConfigureWidgets() = 0;
void Init();
Gtk::Grid m_mainLayout;
GtkmmWindow m_window;
};
template<typename GtkmmWindow>
Window<GtkmmWindow>::Window()
{
m_window.add(m_mainLayout);
// When signal 'realize' is sent, 'Init' will be triggered.
// This happens after construction, so virtual methods can
// be used safely:
m_window.signal_realize().connect([this](){Init();});
}
// Initialize child window according to its own needs:
template<typename GtkmmWindow>
void Window<GtkmmWindow>::Init()
{
ConfigureWindow();
ConfigureLayouts();
ConfigureWidgets();
// If this line is removed, no widgets are shown.
m_window.show_all_children();
}
这个类的目标是确保点 1 到 4 由所有窗口以相同的方式实现。它通过在发送realize 信号时调用适当的虚拟方法(在具体子类中重新定义)来实现。这是因为当发送realize 信号时,我知道窗口构造函数已被调用,我可以安全地使用虚方法。
例如,这是我使用它来创建应用程序主窗口的方法:
class MyWindow : public Window<Gtk::ApplicationWindow>
{
public:
MyWindow(Gtk::Application& p_app) : m_app{p_app} {}
int Show() override
{
m_window.show_all();
return m_app.run(m_window);
}
private:
Gtk::Application& m_app;
Gtk::Button m_button;
void ConfigureWindow() override
{
m_window.set_title("SO Question");
// If I set this to false, the window shrinks to fit the button size:
m_window.set_resizable(false);
}
void ConfigureLayouts() override
{
m_mainLayout.override_background_color(Gdk::RGBA("yellow"));
}
void ConfigureWidgets() override
{
m_mainLayout.attach(m_button, 0, 0, 1, 1);
m_button.set_label("Hello");
}
};
此主窗口将主布局设置为具有黄色背景,在主布局中注册了带有标签“Hello”的Gtk::Button。这个策略的问题是,当我运行代码时,我得到了奇怪的窗口/布局大小:
请注意,黄色布局比其中包含的唯一小部件(按钮)大得多。这是我所期望的结果:
也就是说,窗口和主布局应该缩小到它们唯一包含的小部件的大小。奇怪的是,如果我将窗口设为set_resizable(false),我会得到我想要的大小,但是我不能再调整它的大小,这通常是不可接受的。
问题:
- 为什么不是这样(为什么布局占用了这么多额外空间)?
- 如何在不为每个窗口复制基本代码的情况下实现这一点?
您可以使用g++ 构建此代码,方法是将其添加到:
#include <memory>
#include <gtkmm.h>
// Add here...
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "so.realize");
std::unique_ptr<MyWindow> mainWindow = std::make_unique<MyWindow>(*(app.get()));
return mainWindow->Show();
}
并运行:
g++ -std=c++17 main.cpp -o example.out `pkg-config gtkmm-3.0 --cflags --libs`
【问题讨论】: