0

I have a QScrollArea with a number of QTreeWidgets in it arranged into QVBoxLayout. Each tree widget has a single top-level item (but hierarchy of child items is arbitrary). Vertical scrollbars of individual tree widgets are disabled via setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff). I want vertical size of tree widgets to be dynamically changed when their items are expanded or collapsed, so I have set setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents) for each of the QTreeWidgets. Vertical size policies are set to minimum, and there is a vertical spacer put below all tree widgets. Layout spacing is set to 0. Now, it works like expected, except one thing: when a tree widget is entirely collapsed, it still takes too much vertical space, as shown in the picture. I just cannot figure out how to get rid of this extra space, so that the tree widgets were next to each other when collapsed.

enter image description here.

The contents of the ui-form generated in the Qt Designer:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>241</width>
    <height>526</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <property name="spacing">
     <number>0</number>
    </property>
    <property name="sizeConstraint">
     <enum>QLayout::SetMinimumSize</enum>
    </property>
    <property name="leftMargin">
     <number>0</number>
    </property>
    <property name="topMargin">
     <number>0</number>
    </property>
    <property name="rightMargin">
     <number>0</number>
    </property>
    <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
     <widget class="QScrollArea" name="scrollArea">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="styleSheet">
       <string notr="true">background-color: rgb(255, 255, 255);</string>
      </property>
      <property name="frameShape">
       <enum>QFrame::NoFrame</enum>
      </property>
      <property name="lineWidth">
       <number>0</number>
      </property>
      <property name="widgetResizable">
       <bool>true</bool>
      </property>
      <widget class="QWidget" name="scrollAreaWidgetContents">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>241</width>
         <height>480</height>
        </rect>
       </property>
       <layout class="QVBoxLayout" name="verticalLayout_2">
        <property name="spacing">
         <number>10</number>
        </property>
        <property name="leftMargin">
         <number>0</number>
        </property>
        <property name="topMargin">
         <number>0</number>
        </property>
        <property name="rightMargin">
         <number>0</number>
        </property>
        <property name="bottomMargin">
         <number>0</number>
        </property>
        <item>
         <widget class="QTreeWidget" name="treeWidget">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
            <horstretch>0</horstretch>
            <verstretch>0</verstretch>
           </sizepolicy>
          </property>
          <property name="frameShape">
           <enum>QFrame::NoFrame</enum>
          </property>
          <property name="lineWidth">
           <number>0</number>
          </property>
          <property name="verticalScrollBarPolicy">
           <enum>Qt::ScrollBarAlwaysOff</enum>
          </property>
          <property name="horizontalScrollBarPolicy">
           <enum>Qt::ScrollBarAlwaysOff</enum>
          </property>
          <property name="sizeAdjustPolicy">
           <enum>QAbstractScrollArea::AdjustToContents</enum>
          </property>
          <property name="alternatingRowColors">
           <bool>false</bool>
          </property>
          <property name="uniformRowHeights">
           <bool>false</bool>
          </property>
          <property name="animated">
           <bool>false</bool>
          </property>
          <property name="headerHidden">
           <bool>true</bool>
          </property>
          <attribute name="headerVisible">
           <bool>false</bool>
          </attribute>
          <column>
           <property name="text">
            <string>New Column</string>
           </property>
          </column>
          <item>
           <property name="text">
            <string>TreeWidget1</string>
           </property>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
            <item>
             <property name="text">
              <string>New Item</string>
             </property>
            </item>
            <item>
             <property name="text">
              <string>New Item</string>
             </property>
            </item>
            <item>
             <property name="text">
              <string>New Item</string>
             </property>
            </item>
            <item>
             <property name="text">
              <string>New Item</string>
             </property>
            </item>
           </item>
          </item>
         </widget>
        </item>
        <item>
         <widget class="QTreeWidget" name="treeWidget_2">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
            <horstretch>0</horstretch>
            <verstretch>0</verstretch>
           </sizepolicy>
          </property>
          <property name="frameShape">
           <enum>QFrame::NoFrame</enum>
          </property>
          <property name="lineWidth">
           <number>0</number>
          </property>
          <property name="verticalScrollBarPolicy">
           <enum>Qt::ScrollBarAlwaysOff</enum>
          </property>
          <property name="horizontalScrollBarPolicy">
           <enum>Qt::ScrollBarAlwaysOff</enum>
          </property>
          <property name="sizeAdjustPolicy">
           <enum>QAbstractScrollArea::AdjustToContents</enum>
          </property>
          <property name="autoScroll">
           <bool>true</bool>
          </property>
          <attribute name="headerVisible">
           <bool>false</bool>
          </attribute>
          <column>
           <property name="text">
            <string>1</string>
           </property>
          </column>
          <item>
           <property name="text">
            <string>TreeWidget2</string>
           </property>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
          </item>
         </widget>
        </item>
        <item>
         <widget class="QTreeWidget" name="treeWidget_3">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
            <horstretch>0</horstretch>
            <verstretch>0</verstretch>
           </sizepolicy>
          </property>
          <property name="frameShape">
           <enum>QFrame::NoFrame</enum>
          </property>
          <property name="lineWidth">
           <number>0</number>
          </property>
          <property name="verticalScrollBarPolicy">
           <enum>Qt::ScrollBarAlwaysOff</enum>
          </property>
          <property name="horizontalScrollBarPolicy">
           <enum>Qt::ScrollBarAlwaysOff</enum>
          </property>
          <property name="sizeAdjustPolicy">
           <enum>QAbstractScrollArea::AdjustToContents</enum>
          </property>
          <property name="autoScroll">
           <bool>true</bool>
          </property>
          <property name="autoScrollMargin">
           <number>0</number>
          </property>
          <attribute name="headerVisible">
           <bool>false</bool>
          </attribute>
          <column>
           <property name="text">
            <string>1</string>
           </property>
          </column>
          <item>
           <property name="text">
            <string>TreeWidget3</string>
           </property>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
           <item>
            <property name="text">
             <string>New Item</string>
            </property>
           </item>
          </item>
         </widget>
        </item>
        <item>
         <spacer name="verticalSpacer">
          <property name="orientation">
           <enum>Qt::Vertical</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
            <width>17</width>
            <height>82</height>
           </size>
          </property>
         </spacer>
        </item>
       </layout>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>241</width>
     <height>24</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>treeWidget</sender>
   <signal>currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)</signal>
   <receiver>treeWidget_2</receiver>
   <slot>clearSelection()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>33</x>
     <y>42</y>
    </hint>
    <hint type="destinationlabel">
     <x>31</x>
     <y>172</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>treeWidget</sender>
   <signal>currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)</signal>
   <receiver>treeWidget_3</receiver>
   <slot>clearSelection()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>94</x>
     <y>76</y>
    </hint>
    <hint type="destinationlabel">
     <x>43</x>
     <y>271</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>treeWidget_2</sender>
   <signal>currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)</signal>
   <receiver>treeWidget</receiver>
   <slot>clearSelection()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>95</x>
     <y>179</y>
    </hint>
    <hint type="destinationlabel">
     <x>91</x>
     <y>112</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>treeWidget_2</sender>
   <signal>currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)</signal>
   <receiver>treeWidget_3</receiver>
   <slot>clearSelection()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>122</x>
     <y>188</y>
    </hint>
    <hint type="destinationlabel">
     <x>137</x>
     <y>280</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>treeWidget_3</sender>
   <signal>currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)</signal>
   <receiver>treeWidget</receiver>
   <slot>clearSelection()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>193</x>
     <y>296</y>
    </hint>
    <hint type="destinationlabel">
     <x>167</x>
     <y>115</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>treeWidget_3</sender>
   <signal>currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)</signal>
   <receiver>treeWidget_2</receiver>
   <slot>clearSelection()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>217</x>
     <y>295</y>
    </hint>
    <hint type="destinationlabel">
     <x>217</x>
     <y>226</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>

A relevant piece of the translated code from the ui-form:

    centralwidget = new QWidget(MainWindow);
    centralwidget->setObjectName(QStringLiteral("centralwidget"));
    verticalLayout = new QVBoxLayout(centralwidget);
    verticalLayout->setSpacing(0);
    verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
    verticalLayout->setSizeConstraint(QLayout::SetMinimumSize);
    verticalLayout->setContentsMargins(0, 0, 0, 0);
    scrollArea = new QScrollArea(centralwidget);
    scrollArea->setObjectName(QStringLiteral("scrollArea"));
    QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    sizePolicy.setHorizontalStretch(0);
    sizePolicy.setVerticalStretch(0);
    sizePolicy.setHeightForWidth(scrollArea->sizePolicy().hasHeightForWidth());
    scrollArea->setSizePolicy(sizePolicy);
    scrollArea->setStyleSheet(QStringLiteral("background-color: rgb(255, 255, 255);"));
    scrollArea->setFrameShape(QFrame::NoFrame);
    scrollArea->setLineWidth(0);
    scrollArea->setWidgetResizable(true);
    scrollAreaWidgetContents = new QWidget();
    scrollAreaWidgetContents->setObjectName(QStringLiteral("scrollAreaWidgetContents"));
    scrollAreaWidgetContents->setGeometry(QRect(0, 0, 241, 480));
    verticalLayout_2 = new QVBoxLayout(scrollAreaWidgetContents);
    verticalLayout_2->setSpacing(10);
    verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
    verticalLayout_2->setContentsMargins(0, 0, 0, 0);
    treeWidget = new QTreeWidget(scrollAreaWidgetContents);
    QTreeWidgetItem *__qtreewidgetitem = new QTreeWidgetItem(treeWidget);
    new QTreeWidgetItem(__qtreewidgetitem);
    new QTreeWidgetItem(__qtreewidgetitem);
    new QTreeWidgetItem(__qtreewidgetitem);
    new QTreeWidgetItem(__qtreewidgetitem);
    new QTreeWidgetItem(__qtreewidgetitem);
    new QTreeWidgetItem(__qtreewidgetitem);
    new QTreeWidgetItem(__qtreewidgetitem);
    new QTreeWidgetItem(__qtreewidgetitem);
    new QTreeWidgetItem(__qtreewidgetitem);
    QTreeWidgetItem *__qtreewidgetitem1 = new QTreeWidgetItem(__qtreewidgetitem);
    QTreeWidgetItem *__qtreewidgetitem2 = new QTreeWidgetItem(__qtreewidgetitem1);
    new QTreeWidgetItem(__qtreewidgetitem2);
    treeWidget->setObjectName(QStringLiteral("treeWidget"));
    QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Minimum);
    sizePolicy1.setHorizontalStretch(0);
    sizePolicy1.setVerticalStretch(0);
    sizePolicy1.setHeightForWidth(treeWidget->sizePolicy().hasHeightForWidth());
    treeWidget->setSizePolicy(sizePolicy1);
    treeWidget->setFrameShape(QFrame::NoFrame);
    treeWidget->setLineWidth(0);
    treeWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    treeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    treeWidget->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
    treeWidget->setAlternatingRowColors(false);
    treeWidget->setUniformRowHeights(false);
    treeWidget->setAnimated(false);
    treeWidget->setHeaderHidden(true);
    treeWidget->header()->setVisible(false);

    verticalLayout_2->addWidget(treeWidget);
    //... (other tree-widgets inserted)

   verticalSpacer = new QSpacerItem(17, 82, QSizePolicy::Minimum, QSizePolicy::Expanding);
    verticalLayout_2->addItem(verticalSpacer);
    scrollArea->setWidget(scrollAreaWidgetContents);
    verticalLayout->addWidget(scrollArea);
    MainWindow->setCentralWidget(centralwidget);
Maximko
  • 627
  • 8
  • 20
  • What about `QWidget::adjustSize()`? Try to call it before evaluating new vertical size. http://doc.qt.io/qt-5/qwidget.html#adjustSize It is just not very clear without any code of yours. – Alexander V Jun 25 '18 at 18:18
  • Nope, `QWidget::adjustSize()` makes no difference. I also added a piece of code in the post. – Maximko Jun 25 '18 at 18:33
  • @Maximko share your .ui please – eyllanesc Jun 25 '18 at 19:22
  • I've put the .ui in the post. – Maximko Jun 26 '18 at 03:34
  • In fact, I could use a single QTreeWidget, but I need it such that spacing between top-level items should be larger than between standard subitems. I failed to find a solution that would work without resorting to QTreeView and custom delegate. The solution with several QTreeWidgets is Ok but the desired spacing between "top-level" items (individual tree widgets in this case) is too large. – Maximko Jun 26 '18 at 08:32
  • I checked the actual size of the tree widget, through `qDebug() << ui.treeWidget->size()`, and when collapsed, it shows `QSize(100, 21)`. Vertical size 21 is what I expect from a collapsed tree widget (e.g., vertical size of a standard push button in the same window is 31). So QTreeWidget seems to have correct vertical size when collapsed, but then where this extra space comes from? – Maximko Jun 26 '18 at 09:02
  • Can you use style sheets to visualize the different widgets? You could set `#MainWindow { background-color: orange; } QTreeWidget { background-color: green; }` or similar and make another screenshot. Alternatively you could output `mapToGlobal(rect())` of all widgets in your ui. – Martin Hennings Jun 28 '18 at 12:24
  • Has anyone found the solution since? – Olivier Giniaux Mar 11 '20 at 08:08

0 Answers0