Qt布局:小部件大小更改后调整为最小值

39
基本上,我有一个带有几个小部件的QGridLayout。其中重要的是2个标签,我用它们来向屏幕绘制图像。如果用户想要更改传入图像的分辨率,则会强制标签调整大小。
假设标签的初始大小为320x240。用户将VideoMode更改为640x480,标签和整个GUI都可以完美地调整大小。但是当用户切换回320x240时,标签会缩小,但布局/窗口不会。
我已经尝试过sizePolicies、sizeHints和resize(0,0),但没有什么效果。有人能帮我解决这个问题吗?
以下是一些截图以澄清问题:

Here, everything is okay still, 640 x 480 resizes perfectly but here, the layout is too big.


1
我遇到了一个问题,即小部件树中的一个小部件被调整大小,但顶层小部件没有更新其大小。解决方案是在此调整大小的小部件中发出自定义信号,并使用Qt :: QueuedConnection将其连接到主窗口中的自定义槽中。然后,该槽只需执行resize(sizeHint()) - hochl
4个回答

75

您需要将容纳所有小部件的布局的大小约束设置为"SetFixedSize"。尽管名称听起来似乎无法工作,但它确保您的布局仅使用所需的空间。您就不会像第二个屏幕截图中那样遇到问题。

示例:

mainLayout.setSizeConstraint(QLayout::SetFixedSize);

5
谢谢!这样做省去了我再花几个小时搜索和调试,这都是因为这个可怕的命名。为什么SetFixedSize暗示着“自动调整到最小尺寸”,这从语义上来说并不是一个固定的大小,因为最小尺寸取决于小部件内容的(潜在动态)大小?这是否有任何解释? - hgross
1
这个名称并没有太多意义,而且我已经有一段时间没有使用Qt了,所以我不记得我是怎么发现这个问题的。但是这个问题困扰了我一段时间。很高兴它对你有帮助。 - user929404
1
没事了,我发现可以将其设置为“忽略”,让子部件的大小策略决定大小(请参见此处的最后一条回复:http://www.qtcentre.org/threads/7593-QScrollArea-and-resizing) - Assimilater
没事了,nvm,它不再扩展以适应子内容。也许我需要问一个单独的问题... - Assimilater
1
不错,这是一个漫长的搜索,为了做对它! - Ben
显示剩余2条评论

11

当您希望始终将小部件大小固定在其“打包”大小上时,QLayout :: setSizeConstraint(QLayout :: SetFixedSize)可以很好地解决这个问题。即,如果您希望始终将其固定为正确尺寸,则仍可能因子窗口小部件的更改而发生变化。这就是“fixed” 在这里的含义:即使后者变化,也要固定在正确大小上。(在Qt术语中,我所说的“packed”大小只是小部件的sizeHint。)

但是,在某些情况下,约束可能过于强大。特别是,如果将其应用于顶级窗口,则用户将无法自由调整窗口大小。如果不喜欢那样,您可以每次需要时瞬间执行“设置大小为sizeHint”操作,而不是将其作为无情的限制施加。方法是调用QWidget :: adjustSize()。

http://doc.qt.io/qt-5/qwidget.html#adjustSize

请注意,如果更改大小的容器不是顶级窗口,则可能需要递归地在容器及其父项上调用adjustSize()。(在我的案例中,我必须这样做。我还尝试了大小约束方案,并发现仅在最高级别应用约束可以成功压缩所有级别。我对Qt的了解不足以对这些观察有用的评论,因此我只是分享它们。)


2

在对布局进行任何更改之前,您需要存储小部件父窗口的原始大小,并在用户切换回原始大小时恢复它。

请注意,您需要使用小部件父窗口的大小而不是小部件父级的大小。

在对布局进行更改之前,请在您的小部件中执行此操作:

minimumWindowSize = this->window().size();

当您完成重新组织小部件到紧凑大小时。
this->window().resize(minimumWindowSize);

谢谢,我会在几分钟内尝试。事实上,有许多不同的分辨率组合,从320x240到1280x1024。这将需要最多10个大小配置。Qt没有自动完成这项任务的方法吗? - Hafnernuss
我没有测试过,但你可以尝试只存储最小的大小(甚至提供一个空大小)。如果我没错的话,QT应该会自动增加窗口大小到最小值以显示所有包含的小部件。 - Pierluigi

1

这正是我在项目中所做的。操作系统的分辨率并不重要,我只需要一个小部件来渲染视频或图像。

void MainWindow::resizeEvent(QResizeEvent* event)
 {
   QMainWindow::resizeEvent(event);
   if ((player != 0) && ((player->isPlaying()) || player->isLoaded() || player>isLoaded())){
     renderer->resize(ui->mainVideoWidget->width(),ui->mainVideoWidget->height());
     resizeFilter();

 }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接