GTK+ 中的缩小窗口当内容缩小时动态变化?

发布于 2024-12-27 16:31:06 字数 413 浏览 3 评论 0原文

我在 Vala 应用程序中有一个窗口,里面有一个图像。 该图像有时会被 img.set_from_pixbuf(imgdata); 更改,因此它的大小也会发生变化。它嵌入在 Gtk.Box 中。

box = new Gtk.Box(Orientation.VERTICAL,5);
...
box.pack_end(img,false,false);

因此,如果之前有一张大图像,然后我用较小的图像替换它,则窗口仍然大得离谱,而且我还没有找到一种方法将其动态缩小到所需的空间。 我尝试过 window.set_default_size(box.width_request,box.height_request) 但它总是返回 -1。

那么有什么想法如何调整窗口大小吗? 谢谢!

I have a window in a Vala application and an image inside it.
This image is changed sometimes by img.set_from_pixbuf(imgdata); and so it's size changes as well. It's embedded in a Gtk.Box.

box = new Gtk.Box(Orientation.VERTICAL,5);
...
box.pack_end(img,false,false);

So if there was a big image before and I replace it with a smaller one, the window remains ridiculously big and I have not found a method to dynamically shrink it to the space required.
I have tried with window.set_default_size(box.width_request,box.height_request) but it always returns -1.

So any ideas how to resize the window?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明媚如初 2025-01-03 16:31:06

我自己也曾与这个问题作过斗争,虽然接受的答案是正确的,但我想我可以用工作代码给出一个更“完整”的答案。

重现问题

以下代码(抱歉,在 C++ 中)重现了您的问题:

#include <array>

#include <gtkmm.h>

class ResizableWindow : public Gtk::Window
{

public:

    ResizableWindow()
    : m_toggle{"Toggle"}
    , m_currentImageIndex{0}
    {
        m_files[0] = "small.png";
        m_files[1] = "large.png";
    
        // Setup window layout:
        m_layout.attach(*Gtk::manage(new Gtk::Image(m_files[m_currentImageIndex])), 0, 0, 1, 1);
        m_layout.attach(m_toggle, 0, 1, 1, 1);
        add(m_layout);
        
        // Set up signal handlers:
        m_toggle.signal_clicked().connect([this](){OnToggle();});
    }

private:

    void OnToggle()
    {
        // Switch image file:
        if(m_currentImageIndex == 0)
        {
            m_currentImageIndex = 1;
        }
        else
        {
            m_currentImageIndex = 0;
        }
        
        // Load new image.
        Gtk::Widget* child = m_layout.get_child_at(0, 0);
        Gtk::Image* currentImage = dynamic_cast<Gtk::Image*>(child);
        
        currentImage->set(m_files[m_currentImageIndex]);
    }

    Gtk::Grid m_layout;
    
    Gtk::Button m_toggle;
    
    std::array<std::string, 2> m_files;
    size_t m_currentImageIndex;
};

int main (int argc, char* argv[])
{
    auto app = Gtk::Application::create(argc, argv, "so.question.q8903140");
    
    ResizableWindow w;
    w.show_all();

    return app->run(w);
}

Toggle 按钮更改底层图像。两者是相同的图像,但大小不同。请注意,正如您已经提到的,第一次切换时(小 --> 大),窗口会适当调整大小。但是,当第二次切换时(大 --> 小),图像会调整大小,但窗口不会调整,从而在图像周围留下额外的空间:

在此处输入图像描述

奇怪,我知道......

方案

解决 这个问题,需要打电话给调整大小方法。因此,Toggle 处理程序将变为:

void OnToggle()
{
    if(m_currentImageIndex == 0)
    {
        m_currentImageIndex = 1;
    }
    else
    {
        m_currentImageIndex = 0;
    }
    
    Gtk::Widget* child = m_layout.get_child_at(0, 0);
    Gtk::Image* currentImage = dynamic_cast<Gtk::Image*>(child);
    
    currentImage->set(m_files[m_currentImageIndex]);
    
    // Resize window:
    resize(1, 1);
}

请注意,resize 是使用尺寸 1x1(可能的最小尺寸)调用的。 GTkmm 将根据几何约束自动调整窗口大小。

I have fought with this issue myself and while the accepted answer is correct, I though I could give a more "complete" answer, with working code.

Reproducing the problem

The following code (In C++, sorry) reproduces your issue:

#include <array>

#include <gtkmm.h>

class ResizableWindow : public Gtk::Window
{

public:

    ResizableWindow()
    : m_toggle{"Toggle"}
    , m_currentImageIndex{0}
    {
        m_files[0] = "small.png";
        m_files[1] = "large.png";
    
        // Setup window layout:
        m_layout.attach(*Gtk::manage(new Gtk::Image(m_files[m_currentImageIndex])), 0, 0, 1, 1);
        m_layout.attach(m_toggle, 0, 1, 1, 1);
        add(m_layout);
        
        // Set up signal handlers:
        m_toggle.signal_clicked().connect([this](){OnToggle();});
    }

private:

    void OnToggle()
    {
        // Switch image file:
        if(m_currentImageIndex == 0)
        {
            m_currentImageIndex = 1;
        }
        else
        {
            m_currentImageIndex = 0;
        }
        
        // Load new image.
        Gtk::Widget* child = m_layout.get_child_at(0, 0);
        Gtk::Image* currentImage = dynamic_cast<Gtk::Image*>(child);
        
        currentImage->set(m_files[m_currentImageIndex]);
    }

    Gtk::Grid m_layout;
    
    Gtk::Button m_toggle;
    
    std::array<std::string, 2> m_files;
    size_t m_currentImageIndex;
};

int main (int argc, char* argv[])
{
    auto app = Gtk::Application::create(argc, argv, "so.question.q8903140");
    
    ResizableWindow w;
    w.show_all();

    return app->run(w);
}

The Toggle button changes the underlying images. Both are the same image, but with different sizes. Notice that, As you already mentionned, when toggling for the first time (small --> large), the window resizes appropriately. However, when toggling a second time (large --> small), the image is resized, but not the window, leaving extra space around the image:

enter image description here

Weird, I know...

Solution

To solve the issue, one needs to call the resize method. So the Toggle handler would become:

void OnToggle()
{
    if(m_currentImageIndex == 0)
    {
        m_currentImageIndex = 1;
    }
    else
    {
        m_currentImageIndex = 0;
    }
    
    Gtk::Widget* child = m_layout.get_child_at(0, 0);
    Gtk::Image* currentImage = dynamic_cast<Gtk::Image*>(child);
    
    currentImage->set(m_files[m_currentImageIndex]);
    
    // Resize window:
    resize(1, 1);
}

Note that resize was called with dimensions 1x1 (smallest possible dimensions). Gtkmm will resize the window following geometry constraints automatically from there.

街角卖回忆 2025-01-03 16:31:06

如果我没有弄错的话,窗口的自动调整大小只会发生在元素太大而无法绘制时。另外, set_default_size 方法仅在第一次绘制窗口时才重要,除非我错了,否则永远不会再次使用。我建议使用调整大小方法来设置窗口大小。 (链接

window.resize(box.width_request, box.height_request);

使用调整大小时需要记住的一件事:如果您使用 set_request_size 方法遇到该问题,则无法将其调整为小于 request_size。

If I am not mistaken the automatic resizing of windows only only happens when elements are too large to be drawn. Additionally the set_default_size method only matters when first drawing the window and unless I am wrong is never used again. I would suggest using the resize method to set the window size. (link)

window.resize(box.width_request, box.height_request);

One thing you need to remember when using resize if you can't resize it smaller than the request_size if you run into that issue use the set_request_size method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文