连接到实现信号:奇怪的窗口大小调整行为

Posted

技术标签:

【中文标题】连接到实现信号:奇怪的窗口大小调整行为【英文标题】:Connecting to the realize signal: strange window sizing behavior 【发布时间】: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_appp_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`

【问题讨论】:

【参考方案1】:

这是网格的默认行为。您可以尝试一个简单的示例,其中包含一个窗口、一个网格和一个按钮。网格内的元素不会自动扩展以占用分配的网格大小。为此,您需要添加

button.set_hexpand(true);
button.set_vexpand(true);

这是关于网格与框的一个很好的参考。 https://people.gnome.org/~ryanl/gtk/html/ch28s02.html

【讨论】:

我知道,我已经尝试过了,它给了我第二个输出(布局的大小等于按钮的大小)。我在问为什么布局在窗口中占用这么多空间而不是调整按钮的大小,就像您所指的简单示例中那样。感谢您的参考。 感谢您的意见,我澄清了这个问题。

以上是关于连接到实现信号:奇怪的窗口大小调整行为的主要内容,如果未能解决你的问题,请参考以下文章

将图像拟合到窗口 - GTKmm

覆盖winform窗口的调整大小行为

调整窗口大小会导致位图被覆盖

无法连接到 GTKMM signal_configure_event

如何创建具有多个显示三角形的调整大小窗口?

vim打开时窗口大小怎么调整,在_vimrc中怎么设置?