Qt删除小部件后调整窗口大小

7
我正在将小部件添加到布局中。
ui->horizontalLayout->addWidget(tabwidget);

当我执行操作时,qmainwindow会自动调整大小。但是随后我进行了...

tabwidget->setVisible(false);
qs = sizeHint();
resize(qs);

我得到的大小就像选项卡小部件没有从窗口中移除一样。

我制作了一个新按钮。

void MainWindow::on_pushButton_2_clicked()
{
    qs = sizeHint();
    resize(qs);
}

并且它提供了正确的尺寸。

看起来我需要一些更新函数,但是我找不到它。请给予建议。


你尝试过 MainWindow::updateGeometry() 吗? - dualed
它没有帮助。void QWidget::updateGeometry() 通知布局系统此小部件已更改并可能需要更改几何形状。而 tabWidget->updateGeometry() 也不起作用。 - quux
这很奇怪,这并不是一个不常见的用例,为了确保,您也尝试过在布局上使用update()repaint()invalidate()等吗? - dualed
2个回答

7
这是由于Qt内部的一个长期问题引起的(我记得首次在Qt3中遇到它)。顶部小部件需要接收事件才能真正更新其几何形状并了解其边界。这个事件似乎总是在布局生成的调整大小事件之后接收到,因此缩小小部件总是太晚了。
已接受答案中发布的解决方案有效。但是,在布局之后添加下面的更简单的解决方案也可以起作用:
layout()->removeWidget( widget );

QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
resize( sizeHint() );

基本上我们需要做的就是让事件循环运行并传递必要的事件,以便在运行resize()之前更新顶层小部件的几何形状。
请注意,如果您有多个线程运行或者有事件传递到您的插槽中,此代码可能会产生副作用。因此,在resize()之后最好不要在此函数中添加任何代码。

我尝试使用Qt5,效果非常好。这是一个非常简单的解决方案。只需要阅读一下文档,就可以弄清楚它的实际工作原理了。 - Lightbulb1
基本上我们所需要的就是让事件循环运行并传递必要的事件,以便在运行resize()之前更新顶部窗口小部件的几何形状。 - Phiber

5
如果按钮插槽给出了正确的结果,那么您可以始终在由单次定时器调用的插槽中调用sizeHint()和随后的resize()
void MainWindow::fixSize()
{
    QSize size = sizeHint();
    resize(size);
}

void MainWindow::methodWhereIHideTheTabWidget()
{
    tabwidget->setVisible(false);
    QTimer::singleShot(0, this, SLOT(fixSize()));
}

这个计时器被设置为零延迟。这意味着当程序返回到主循环并且内部小部件状态得到更新后,插槽将立即被调用。如果这不能解决您的问题,则可以尝试将零替换为1。


3
如果只有在添加 35 毫秒延迟后才能正常工作,而使用 34 毫秒延迟时无法正常工作,那么我不会依赖它。如果运行该软件的计算机出现“抽搐”并且没有给足够的 CPU 时间给你的程序,那么事情可能会出错。 - ZalewaPL

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