Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shrink window in GTK+ dynamically when content shrinks?

Tags:

linux

gtk

vala

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!

like image 526
muxamilian Avatar asked Jan 17 '12 23:01

muxamilian


2 Answers

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.

like image 200
Mindbane Avatar answered Nov 15 '22 16:11

Mindbane


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.

like image 40
BobMorane Avatar answered Nov 15 '22 16:11

BobMorane