Search code examples
c++qtuser-interfaceqt4qdockwidget

How to make Qt subwidget height equal?


I have some QDockWidgets (not floating, only closable) inside a single QWidget. I have some widgets inside each QDockWidget - their heights should be equal. These inner widgets can be hidden through the context menu.

My inner widgets should have equal height. I done it this way:

void MyDocksPanel::redistributeSpace()
{
    QBoxLayout * lay = (QBoxLayout *)layout();
    for (int i = 0; i < lay->count(); i++)
    {
        QWidget * dock = lay->itemAt(i)->widget();
        if (dock == NULL)
            continue;

        int size = 0;
        foreach(QWidget * subWidget, dock->findChildren<QWidget*>())
            size += subWidget->isVisible() ? 1 : 0;

        if (dock->isVisible() && (size == 0))
            dock->hide();
        lay->setStretch(i, size);
    }
}

All works fine until I add some const elements to each QDockWidget: some horizontal scrollbars and some Labels... Now my inner widgets have different sizes. But it is necessary for me to set their heights strongly equal.

QLayout lays out widget sizes on one level of a widget's hierarchy. How can I make height-equal subwidgets?

3 subwidgets vs 2 subwidgets

First picture

My first strategy to set stretches 3 and 2:

enter image description here

But, when i have added scroll bars:

enter image description here

Heights of my 5 widgets are equals to 37,37,37,28,28 ... and thats the problem


Solution

  • You're on the right track with the stretch factors, but think in terms of pixel values rather than small proportions. Try setting the stretch factor of each dock widget to this:

    dockWidgetStretch = numChildWidgets * childWidgetMinimumHeight + scrollBarHeight;
    

    where childWidgetMinimumHeight and scrollBarHeight are both expressed in pixels, and are both constants.

    EDIT: Here is a working example. You might have to experiment a bit to get it to work with your program, but this should be a good start.

    header.h

    #include <QtGui>
    
    class WidgetWith3Children : public QWidget
    {
    public:
        WidgetWith3Children()
        {
            QTextEdit *edit1 = new QTextEdit;
            QTextEdit *edit2 = new QTextEdit;
            QTextEdit *edit3 = new QTextEdit;
            QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
            QVBoxLayout *layout = new QVBoxLayout;
            layout->addWidget(edit1);
            layout->addWidget(edit2);
            layout->addWidget(edit3);
            layout->addWidget(scrollBar);
            setLayout(layout);
        }
    };
    
    class WidgetWith2Children : public QWidget
    {
    public:
        WidgetWith2Children()
        {
            QTextEdit *edit1 = new QTextEdit;
            QTextEdit *edit2 = new QTextEdit;
            QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
            QVBoxLayout *layout = new QVBoxLayout;
            layout->addWidget(edit1);
            layout->addWidget(edit2);
            layout->addWidget(scrollBar);
            setLayout(layout);
        }
    };
    
    class OuterWidget : public QWidget
    {
    public:
        OuterWidget()
        {
            QDockWidget *dockWidget1 = new QDockWidget;
            QDockWidget *dockWidget2 = new QDockWidget;
            dockWidget1->setWidget(new WidgetWith3Children);
            dockWidget2->setWidget(new WidgetWith2Children);
            QVBoxLayout *layout = new QVBoxLayout;
    
            // 71 is the height of the minimum size hint for QTextEdit
            // 30 is the height of a horizontal scrollbar (on my system)
            layout->addWidget(dockWidget1, 71 * 3 + 30);
            layout->addWidget(dockWidget2, 71 * 2 + 30);
    
            layout->setMargin(0);
            setLayout(layout);
        }
    };
    

    main.cpp

    #include <QtGui/QApplication>
    #include "header.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        OuterWidget w;
        w.show();
    
        return a.exec();
    }