Initial size of QToolBox is not suitable for its content



  • I just built a small dialog with Qt Designer. It is structured like this:

    QDialog D (using QVBoxLayout)
     |-- QToolBox t
     |-- QVerticalSpacer s
     |-- QDialogButtonBox b
    

    The toolbox is filled with several QColorDialogs, each fills one page. Now when I open the dialog, it looks like this (notice the scrollbars):
    https://abload.de/img/wrongscrollbarsf9ubo.png

    I assumed I had to play around with QWidget::sizePolicy or QLayout::sizeConstraint so the resulting dialog is properly sized independently of the currently used font, fontsize, OS, etc. without the need to show any scrollbars. But that was not enough.

    I have come across this "problem" before, it basically occurs for me when there is more than one top-level layout at work (in this case I assume the toolBox and/or the QColorDialogs contain a layout of their own).

    Does anybody know which switches I have to flip so the dialog is not too small for its content?


  • Lifetime Qt Champion

    Hi,

    Are all those elements put in a layout ? I mean the content of the tool box.



  • No, the content is added to the toolbox via addItem, similar to QToolBox::addItem(new QColorDialog(), "text"). There might be some form of an automatic layout, though.


  • Lifetime Qt Champion

    Can you write a minimal compilable example that show that behavior ?



  • I can.

    1. create a standard Qt Widgets Application based on a QDialog
    2. edit the window to include a QToolBox
    3. set the layout to be vertical (others probably show the same behavior)
    4. remove the widgets that are already included in the QToolBox (has to be done manually, I believe)
    5. edit dialog.cpp to add in a QColorDialog
    6. The resulting dialog (note the scrollbars): https://abload.de/img/dialog_demonstrationsdk0f.png

    I will include the full source code, even though only Dialog::Dialog(QWidget *parent) has been modified.

    dialog.cpp (only added the QColorDialog)

    #include <QColorDialog>
    
    #include "dialog.h"
    #include "ui_dialog.h"
    
    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
        ui->setupUi(this);
    
        QColorDialog *c1 = new QColorDialog(this);
        c1->setOptions(QColorDialog::NoButtons | QColorDialog::DontUseNativeDialog);
        ui->toolBox->addItem(c1, "Colors");
    }
    
    Dialog::~Dialog()
    {
        delete ui;
    }
    

    dialog.ui (edited as described above)

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>Dialog</class>
     <widget class="QDialog" name="Dialog">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>400</width>
        <height>300</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Dialog</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout">
       <item>
        <widget class="QToolBox" name="toolBox">
         <property name="currentIndex">
          <number>-1</number>
         </property>
        </widget>
       </item>
      </layout>
     </widget>
     <layoutdefault spacing="6" margin="11"/>
     <resources/>
     <connections/>
    </ui>
    

    The code I removed from dialog.ui to get rid of the standard widgets looked like this (i.e. it wasn't anything special):

         <widget class="QWidget" name="page">
          <property name="geometry">
           <rect>
            <x>0</x>
            <y>0</y>
            <width>384</width>
            <height>221</height>
           </rect>
          </property>
          <attribute name="label">
           <string>Page 1</string>
          </attribute>
         </widget>
    

    main.cpp (no changes)

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

    dialog.h (no changes)

    #ifndef DIALOG_H
    #define DIALOG_H
    
    #include <QDialog>
    
    namespace Ui {
    class Dialog;
    }
    
    class Dialog : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit Dialog(QWidget *parent = 0);
        ~Dialog();
    
    private:
        Ui::Dialog *ui;
    };
    
    #endif // DIALOG_H
    


  • Just as a test, I created another small example with no changes to the code. Just a QDialog containing a QToolBox containing a layout and some elements. Again, there are scrollbars, which I would like to avoid.
    https://abload.de/img/dialog_demol3jaj.png

    Without the toolbox things are resized correctly.



  • It's not a clean solution but you could try to call adjustSize() in the showEvent(...) of the dialog as a workaround?



  • I read that QToolBox does not implement minimumSizeHint() and thus it will not resize to its contents properly. From the documentation it looks like it doesn't implement any of the sizeHint-functions. I also found some code that tries to work around that problem, but with no proper access to the tool boxes members that solution didn't really seem appropriate, either.
    It seems I will have to choose a replacement for QToolBox, it is explicitly not made for this use-case since it cannot resize itself to its contents at all. (That should probably be highlighted in the documentation.)

    EDIT: I edited the title of this thread and made it a "normal" topic since I don't really think that marking it as "solved" would be in order.


  • Lifetime Qt Champion

    Can you point to the resources you found ?



  • I can try, although I don't fully understand yet where the chain is broken and why sizeHint() doesn't seem to help at all.

    According to the documentation of QToolBox it does not reimplement sizeHint() nor minimumSizeHint(). (code)
    Thus calling those methods falls back to the ones implemented in QToolBoxes base class, QFrame, which does reimplement sizeHint() but not minimalSizeHint(). (code) The implementation of sizeHint() basically falls back to the one in QWidget.

    In the end QToolBox has to work with what QWidget provides it with since there is no meaningful override:
    sizeHint (code)
    minimumSizeHint (code)

    Both of these implementations won't do much without a layout, though. QToolBoxes layout is only used to to add buttons and QScrollAreas. QScrollArea does not reimplement minimumSizeHint(), either. (doc, code)

    So at the very least minimumSizeHint() is nowhere to be found in a QToolBar. As soon as I switched to another "multi-widget manager", i.e. QStackedWidget in my case, my problems were gone.


  • Lifetime Qt Champion

    Can you run a little test ?

    What do you get if you call qDebug() << yourToolBox->sizeHint(); before and after it's shown ?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.