2
votes

I'm working on a Qt application that utilises multiple widgets with the following hierarchy (as seen in Qt Designer):

----- 1. QMainWindow
  |
  |----- 2. QWidget ("central widget")
  |  |
  |  |----- 3. CustomWidget
  |  |
  |  |----- 4. QScrollBar
  |
  |----- 5. QStatusBar
  |
  |----- 6. QToolBar ("top-left toolbar")
  |
  |----- 7. QToolBar ("top-right toolbar")

Which are arranged like this:

(1) ------------------------------
    | (6)         | (7)          |
    |----------------------------|
    | (3)                  | (4) |
    |                      |     |
    |                      |     |
    |                      |     |
    ------------------------------
    | (5)                        |
    ------------------------------

(Note that the central widget has been purposefully omitted as it doesn't appear as an obviously distinct component.)

A settings file dictates whether or not the QStatusBar should show debug information. If it shouldn't, then the QStatusBar should be hidden. The QStatusBar is not hidden by default; it is only hidden once the settings file is read. To do this, I use the QWidget::hide() method.

Sure enough, the QStatusBar is hidden. However, the remaining widgets (specifically the CustomWidget and the QScrollBar) don't expand to fill the space left by the (now hidden) QStatusBar.

I've found the QWidget::update() and QWidget::repaint() methods but they don't seem to be of much use here. (I've tried using them on the QStatusBar widget as well as QMainWindow, the central widget, QScrollBar, and CustomWidget, to no avail.)

I've read the Qt page on size policy which seems to be promising. I'm using the following size policy settings:

  • QMainWindow: 'Preferred' (horizontal and vertical)
  • Central widget: 'Expanding' (horizontal and vertical)
  • QToolBars: 'Preferred' (horizontal), 'Fixed' (vertical)
  • QStatusBar: 'Preferred' (horizontal and vertical)
  • CustomWidget: 'Expanding' (horizontal and vertical)
  • QScrollBar: 'Fixed' (horizontal), 'Expanding' (vertical)

The idea is that the central widget should fill up the space not taken up by the two QToolBars and the QStatusBar. The CustomWidget should then fill up all of the space in the central widget not used by the (vertical) QScrollBar. However, these size policies seem to be totally disregarded - the QStatusBar disappears but the other widgets don't fill up the space.

I suspect the answer may lie in layout management in Qt, but having played with this in Qt Designer (which looks like it applies the various layout classes per widget) I can't find an arrangement that makes this work.

What do I need to do to make the CustomWidget and QScrollBar utilise the space left over when the QStatusBar is hidden?

Edit

I've implemented a kludge in the mean-time by resizing the QMainWindow by one pixel and back again. The resize event seems to reflow the widgets in the manner I'd like. This is an inelegant solution and there must be a way to do this properly!

1

1 Answers

1
votes

After perusing the code for QMainWindowLayout, specifically sizeHint, it appears this is normal behavior implemented in a private class. Basically, when the status bar is hidden or shown, nothing else is to change.

To change this, override QMainWindow::sizeHint like so:

QSize MyMainWindow::sizeHint() const
{
    QSize hint = QMainWindow::sizeHint();
    // if the status bar is invisible, add its height to the return value
    if (statusBar() && !statusBar()->isVisible())
        hint.rheight() += statusBar().sizeHint().height();
    return hint;
}

Edit
This is the simplest possibility I can think of for a solution. If it does not work, the next step would involve reimplementing resizeEvent and checking if it is the result of the status bar hiding.