4

I am creating a widget which contains a chess table and six buttons which are displayed in 2 rows beneath the chess table. The button rows are wider than the chess table. Chess table and buttons are in a QGridLayout. Chess table has its own sizeHint calculated from the size of the squares.

After some operations I delete the buttons and resize the widget that contains everything to its sizeHint (resize(sizeHint())). The widget resizes properly in the vertical direction but in the horizontal direction it remains as wide as if the button rows were there. What is the problem ?

If I construct the widget only with the chess table the layout sizes the widget properly.

I am adding the code:

In the constructor of the window:

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

formLayout = new QGridLayout;

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

setLayout(formLayout);

In the function that adds the buttons:

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);

In the function that deletes everything besides the chess table:

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());

The sizeHint for the chess table is calculated as:

return QSize(m_rowNo*spacing, m_colNo*spacing)+QSize(31,31);
Botz3000
  • 39,020
  • 8
  • 103
  • 127
Cristi
  • 648
  • 1
  • 13
  • 28

1 Answers1

4
  1. You must activate() the layout before for its sizeHint(), and subsequently the widget's sizeHint(), to be updated immediately after modifying the laid out widgets.

  2. The calls to layout->removeWidget() are redundant. Simply delete the unneeded widgets. Qt handles all memory allocation in QWidget hierarchies. Deleting a QWidget without telling anyone on the Qt end of things is safe. There are sane exceptions of course: you can't delete a widget whose method is somewhere on the call stack, for example.

  3. If you don't want to bother with calling resize(), you can set the appropriate size constraint on the widget's layout. For example:

    layout->setSizeConstraint(QLayout::SetFixedSize);

    This ensures that the widget will size itself only large enough to fit the contents per the sizeHint().

Taking points 1 and 2 into account, the function that 'deletes everything besides the chess table' might look like the below:

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

    formLayout->activate();
    resize(sizeHint());
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • According to `QLayout`'s documentation for `activate()`: "You should generally not need to call this because it is automatically called at the most appropriate times." I suggest to use `QWidget::updateGeometry()` to notify Qt about the layout changes. – Johannes S. Jun 19 '12 at 07:39
  • Thank you Kuba Ober. I added the activate() function and resizing worked corectly. updateGeometry() does not do the job. – Cristi Jun 19 '12 at 09:36
  • Johannes: `updateGeometry()` would be a redundant thing to call. It merely notifies the layout system that stuff has changed. There's no need to notify it, because deletion of laid out widgets does it already. I think the only good reason to call `updateGeometry()` is when you update `sizeHint()` or minimum/maximum sizes in a widget. A call to `activate()` forces the layout system to recalculate the layouts there and now. Normally it'd have been deferred to the event loop -- after the `resize(....)` call that then uses stale `sizeHint()` from old state of layouts. Qt docs are sometimes wrong. – Kuba hasn't forgotten Monica Jun 19 '12 at 12:10