我自己已经解决了这个问题,虽然接受的答案是正确的,但我可以用工作代码给出更“完整”的答案。
重现问题
以下代码(在 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
按钮更改底层图像。两者是相同的图像,但大小不同。请注意,正如您已经提到的,当第一次切换时(小 --> 大),窗口会适当地调整大小。但是,当第二次切换时(大 --> 小),图像会被调整大小,而不是窗口,从而在图像周围留下额外的空间:

奇怪,我知道...
解决方案
要解决这个问题,需要调用该resize
方法。所以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 将根据几何约束自动从那里调整窗口大小。