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!
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.
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.
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:
Weird, I know...
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With