【问题标题】:qt resize window after widget remove小部件删除后qt调整窗口大小
【发布时间】:2012-12-18 22:34:35
【问题描述】:

我正在布局中添加小部件

ui->horizontalLayout->addWidget(tabwidget);

并且 qmainwindow 会自行调整大小。但后来我做到了

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

我得到像 tabwidget 这样的大小没有从窗口中删除。

我制作了新按钮

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

它给出了正确的尺寸。

似乎我需要一些更新功能,但我找不到。请指教

【问题讨论】:

  • 你试过MainWindow::updateGeometry()吗?
  • 它没有帮助。 void QWidget::updateGeometry () Notifies the layout system that this widget has changed and may need to change geometry. 而 tabWidget->updateGeometry() 也不起作用
  • 这很奇怪,这不是一个不常见的用例,只是为了确定,你也尝试过update()repaint()invalidate()布局等?

标签: c++ qt


【解决方案1】:

这是由长期的 Qt 内部问题引起的(我记得第一次使用 Qt3 时遇到过)。顶部小部件需要接收事件才能真正更新其几何形状并了解其边界。这个事件似乎总是在layout产生resize事件之后才收到,因此总是来不及收缩widget。

已接受答案中发布的解决方案有效。但是,在布局之后添加时,下面发布的更简单的解决方案也可以使用:

layout()->removeWidget( widget );

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

基本上,我们只需要让事件循环运行并传递必要的事件,以便在运行 resize() 之前更新顶部的小部件几何形状。

请注意,如果您有多个线程正在运行,或者有事件传递到您的插槽,则此代码可能会产生副作用。因此,在 resize() 之后不要在此函数中包含任何代码会更安全。

【讨论】:

  • 我用 Qt5 试过这个,效果很好。这是一个如此简单的解决方案。只需阅读一下文档以了解其实际工作原理。
  • Basically all we need is to let the event loop run and deliver the necessary events so the top widget geometry is updated before resize() is run.+1
【解决方案2】:

如果按钮槽为您提供正确的结果,那么您始终可以在由单次计时器调用的槽中调用sizeHint() 和随后的resize()

void MainWindow::fixSize()
{
    QSize size = sizeHint();
    resize(size);
}

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

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

【讨论】:

  • 如果它仅在您添加 35ms 延迟后才有效,并且在您使用 34ms 延迟时不起作用,那么我不会依赖它。如果运行该软件的计算机出现“打嗝”并且没有为您的程序提供足够的 CPU 时间,事情可能会出错。