布局大小提示QWidget

4

我正在创建一个小部件,其中包含一个棋盘和六个按钮,这些按钮显示在棋盘下方的两行中。按钮行比棋盘宽。棋盘和按钮位于QGridLayout中。棋盘根据方格大小计算出自己的sizeHint。

一些操作后,我删除了按钮,并将包含所有内容的小部件调整为其sizeHint的大小(resize(sizeHint()))。小部件在垂直方向上正确地重新调整大小,但在水平方向上,它仍然像按钮行存在时那样宽。问题出在哪里?

如果只使用棋盘构造小部件,则布局会正确调整小部件的大小。

我添加了以下代码:

在窗口的构造函数中:

renderArea = new RenderArea(m_row,m_col,m_grid);

formLayout = new QGridLayout;

formLayout->addWidget(renderArea,0,0,1,3);

setLayout(formLayout);

在添加按钮的函数中:
addPlaneButton = new QPushButton(tr("Add plane"));
cancelButton = new QPushButton(tr("Cancel operation"));
movePlaneButton = new QPushButton(tr("Move plane"));
deletePlaneButton = new QPushButton(tr("Delete plane"));
rotatePlaneButton = new QPushButton(tr("Rotate plane"));
doneButton = new QPushButton(tr("Done"));
doneButton->setEnabled(false);

infoLabel = new QLabel(tr("Welcome to the plane editor"));
statusLabel = new QLabel();

formLayout->addWidget(statusLabel,1,0,1,3);
formLayout->addWidget(infoLabel,2,0,1,3);
formLayout->addWidget(addPlaneButton,3,0);
formLayout->addWidget(movePlaneButton,3,1);
formLayout->addWidget(deletePlaneButton,3,2);
formLayout->addWidget(rotatePlaneButton,4,0);
formLayout->addWidget(cancelButton,4,1);
formLayout->addWidget(doneButton, 4,2);

在删除除棋盘以外所有内容的函数中:
formLayout->removeWidget(addPlaneButton);
formLayout->removeWidget(cancelButton);
formLayout->removeWidget(movePlaneButton);
formLayout->removeWidget(deletePlaneButton);
formLayout->removeWidget(rotatePlaneButton);
formLayout->removeWidget(doneButton);
formLayout->removeWidget(infoLabel);
formLayout->removeWidget(statusLabel);


delete addPlaneButton;
delete cancelButton;
delete movePlaneButton;
delete deletePlaneButton;
delete rotatePlaneButton;
delete doneButton;


delete infoLabel;
delete statusLabel;

resize(sizeHint());

棋盘的sizeHint被计算为:

return QSize(m_rowNo*spacing, m_colNo*spacing)+QSize(31,31);
1个回答

4
  1. 在修改布局小部件后,您必须先调用 activate() 来更新其 sizeHint(),然后是窗口小部件的 sizeHint()

  2. 调用 layout->removeWidget() 是多余的。只需 delete 不需要的窗口小部件即可。Qt 在 QWidget 层次结构中处理所有内存分配。在不告诉 Qt 的情况下删除 QWidget 是安全的。当然,也有一些合理的例外:例如,您不能删除方法在调用堆栈的某个位置的窗口小部件。

  3. 如果您不想麻烦地调用 resize(),则可以在窗口小部件的布局上设置适当的大小约束。例如:

    layout->setSizeConstraint(QLayout::SetFixedSize);

    这将确保窗口小部件仅调整足够大以适应 sizeHint() 的内容。

考虑到第 1 点和第 2 点,"除了国际象棋表格之外删除所有内容" 的函数可能如下所示:

void removeButtons() {
    delete addPlaneButton;
    delete cancelButton;
    delete movePlaneButton;
    delete deletePlaneButton;
    delete rotatePlaneButton;
    delete doneButton;
    delete infoLabel;
    delete statusLabel;

    formLayout->activate();
    resize(sizeHint());
}

根据QLayout的文档中对于activate()的描述:“通常情况下,您不需要调用此函数,因为它会在最合适的时机自动调用。” 我建议使用QWidget::updateGeometry()来通知Qt有关布局更改的信息。 - Johannes S.
感谢 Kuba Ober。我添加了 activate() 函数并且重新调整大小正常工作。updateGeometry() 函数无法完成该工作。 - Cristi
Johannes: 调用updateGeometry()仅是通知布局系统有东西已经改变,这样做是多余的。没有必要通知它,因为已经删除了已布置的小部件。我认为调用updateGeometry()的唯一好处是在更新小部件中的sizeHint()或最小/最大尺寸时。调用activate()会强制布局系统立即重新计算布局。通常情况下,它将被推迟到事件循环 - 在resize(...)调用之后,该调用使用旧状态布局的陈旧的sizeHint()。Qt文档有时是错误的。 - Kuba hasn't forgotten Monica

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