我正在使用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`
这是网格的默认行为。您可以尝试一个简单的示例,其中包含一个窗口,一个网格和一个按钮。网格内的元素不会自动扩展以占据分配的网格大小。为此,您需要添加
button.set_hexpand(true);
button.set_vexpand(true);
这里是关于网格与框的良好参考。 https://people.gnome.org/~ryanl/gtk/html/ch28s02.html