Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QDockWidget ignoring sizeHint() after user resize
Forum Updated to NodeBB v4.3 + New Features

QDockWidget ignoring sizeHint() after user resize

Scheduled Pinned Locked Moved General and Desktop
4 Posts 3 Posters 4.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    LightFractal
    wrote on last edited by
    #1

    Hi!
    I'm trying to create a collapsible dock widget, by subclassing its content widget to override the sizeHint() method.
    It almost works, but when the dock widget gets resized by the user, the size hint is no longer considered.

    Here's a minimal example (some stacked dock widgets and two push buttons to collapse/expand them):

    @
    #ifndef MYWIDGET_H
    #define MYWIDGET_H
    #include <QtWidgets/QWidget>
    #include <QtWidgets/QMainWindow>

    // Content of the dock widgets
    class MyWidget : public QWidget
    {
    Q_OBJECT

    private:
    bool isClosed;

    public slots:
    void setClosed(bool value)
    {
    if (value != isClosed)
    {
    isClosed = value;

    // sizeHint() is changed
    updateGeometry();

    // None of these works :(
    // ((QMainWindow *)(parent()))->updateGeometry();
    // ((QMainWindow *)(parent()))->adjustSize();
    }
    }

    // Wrapper
    void collapse() { setClosed(true); }
    void expand() { setClosed(false); }

    public:
    MyWidget(QWidget *parent = NULL)
    : QWidget(parent)
    {
    isClosed = false;
    }

    QSize sizeHint() const
    {
    if (isClosed)
    return QSize(0, 0);
    else
    return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
    }
    };

    #endif
    @

    Main Window

    @
    #include "ProvaDock.h"
    #include "MyWidget.h"
    #include <QtWidgets/QDockWidget>
    #include <QtWidgets/QPushButton>
    #include <QtWidgets/QHBoxLayout>

    ProvaDock::ProvaDock(QWidget *parent)
    : QMainWindow(parent)
    {
    // Create the central widget
    QPushButton *btnCollapse = new QPushButton(tr("Collapse"));
    QPushButton *btnExpand = new QPushButton(tr("Expand"));
    QHBoxLayout *layout = new QHBoxLayout();
    layout->addWidget(btnCollapse);
    layout->addWidget(btnExpand);

    // Setup the central widget
    QWidget *contents = new QWidget();
    contents->setLayout(layout);
    setCentralWidget(contents);

    // Number of dock widgets to be added
    const unsigned int NDOCKS = 3;

    QDockWidget *lastDock = NULL;
    for (unsigned int i = 0; i < NDOCKS; i++)
    {
    // Create the dock widget
    const QString title = tr("Dock %1").arg(i + 1);
    QDockWidget *newDock = new QDockWidget(title, this);
    newDock->setWidget(new MyWidget(newDock));

    // Add the dock widget to main window
    addDockWidget(Qt::BottomDockWidgetArea, newDock, Qt::Horizontal);

    // Tabify with the last one
    if (lastDock)
    tabifyDockWidget(lastDock, newDock);

    // Signals
    QObject::connect(btnCollapse, SIGNAL(clicked()), (MyWidget *)(newDock->widget()), SLOT(collapse()));
    QObject::connect(btnExpand, SIGNAL(clicked()), (MyWidget *)(newDock->widget()), SLOT(expand()));

    // Track the last dock widget added
    lastDock = newDock;
    }

    showMaximized();
    }
    @

    I read that QMainWindow handles dock widgets with an internal layout, which unfortunately is inaccessible to the programmer.
    Is there a way to "reset" the internal state of this layout (in order to take into account the size hint again)?

    Thanks

    1 Reply Last reply
    0
    • raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      the sizeHint - as the name says ;) - is just a hint. This size is taken into account when the Qt asks for the preferred/best size to layout/show the widget.
      So you can't use sizeHint() to control the widget's size directly.
      To do so you need to set the min/max size and/or resize the widget explicitly.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      0
      • L Offline
        L Offline
        LightFractal
        wrote on last edited by
        #3

        Ok, I spent many hours trying to get things sorted out, but I still need advice :(

        My objective is to extend the QDockWidget API by providing a method setHeight(int value) to change the dock widget's size.
        We have three elements to consider: the content widget, the dock widget and QMainWindow's internal layout, which manages docking and resizing with splitters.

        Here's the alleged internal layout behavior (for horizontally docked widgets):

        • Before user resizing (application startup):
          The splitter position is bounded by widget's minimum/maximum height, and set to be the widget's size hint if valid; if not, the minimum size is chosen.
          Dock widget resizing is completely ignored (the splitter won't move, causing the dock widget to span over the tab bar, http://i.imgur.com/BbLYIaK.jpg).

        • After user resizing:
          The splitter position is still bounded by widget's minimum/maximum height, but the actual position is memorized internally (I suppose).
          Again, dock widget resizing is completely ignored.
          Only by setting minimum=maximum you can change the splitter position, but this disables user resizing.

        Most functional solution yet:
        @
        void setHeight(int value)
        {
        QDockWidget *dockW = this;
        QMainWindow *mainW = dockW ? qobject_cast<QMainWindow *>(dockW->parent()) : NULL;

        // Set the height
        widget()->setMaximumHeight(value);
        widget()->setMinimumHeight(value);

        // Recursively update all the layouts, starting from the main window
        forceUpdate(mainW);

        // Remove the size constraint
        widget()->setMinimumHeight(QWIDGETSIZE_MAX);
        widget()->setMaximumHeight(QWIDGETSIZE_MAX);

        // Another layout update will be scheduled
        }
        @

        After user resizing, the above code works like a charm.
        Prior to that, the subsequent layout update (after the execution of setHeight()) will set the splitter's position to zero, actually undoing what setHeight() has done.

        Is there a workaround to this, or have I run out of luck? :(

        1 Reply Last reply
        0
        • A Offline
          A Offline
          aliks-os
          wrote on last edited by
          #4

          Hello, I have the same problem. Fo you fix it?

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved