Search code examples
pythonpyqtqt-designer

Automatically adjust the height of a `stackedWidget` page to the height of the widgets placed on it


I would like to adjust the height of the stackedWidget so that the height of the QTextEdit widget below it matches the height of the buttons on the active page of the stackedWidget. While the 4 QPushButton on page extended take up the entire space of the stackedWidget, the 2 QPushButton on page normal appear vertically in the middle and still have free space above and below.

But the 2 QPushButton on page normal should be at the top and the QTextEdit widget should be enlarged upwards. How can this be done?


main.py

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        loadUi("mainwindow.ui", self)


def main():
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

mainwindow.ui

<?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>800</width>
    <height>601</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="locale">
   <locale language="English" country="UnitedKingdom"/>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout_2">
    <item row="0" column="0">
     <widget class="QStackedWidget" name="stackedWidget">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="currentIndex">
       <number>0</number>
      </property>
      <widget class="QWidget" name="normal" native="true">
       <layout class="QGridLayout" name="gridLayout">
        <item row="0" column="0">
         <widget class="QPushButton" name="normal_start_button">
          <property name="text">
           <string>Start</string>
          </property>
         </widget>
        </item>
        <item row="0" column="1">
         <widget class="QPushButton" name="normal_stop_button">
          <property name="text">
           <string>Stop</string>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
      <widget class="QWidget" name="extended">
       <layout class="QGridLayout" name="gridLayout_3">
        <item row="0" column="0">
         <widget class="QPushButton" name="extended_quick_start_button">
          <property name="text">
           <string>Quick Start</string>
          </property>
         </widget>
        </item>
        <item row="0" column="1">
         <widget class="QPushButton" name="extended_stop_button">
          <property name="text">
           <string>Stop</string>
          </property>
         </widget>
        </item>
        <item row="1" column="0">
         <widget class="QPushButton" name="extended_slow_start_button">
          <property name="text">
           <string>Slow Start</string>
          </property>
         </widget>
        </item>
        <item row="1" column="1">
         <widget class="QPushButton" name="extended_pause_button">
          <property name="text">
           <string>Pause</string>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
     </widget>
    </item>
    <item row="1" column="0">
     <widget class="QTextEdit" name="output"/>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>24</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

Screenshot of page normal with only 2 QPushButton and unused space above and below:

Screenshot of page <code>normal</code>


Screenshot of page extended with 4 QPushButton and optimal use of the available space:

Screenshot of page <code>extended</code>


Solution

  • QStackedWidget takes as default height the default maximum height of the widget it contains, so in this case a possible solution is to set the height taking as reference the default height of the current widgets.

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow
    from PyQt5.uic import loadUi
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            loadUi("mainwindow.ui", self)
            self.stackedWidget.currentChanged.connect(self.adjustHeight)
            self.adjustHeight()
    
        def adjustHeight(self):
            h = self.stackedWidget.currentWidget().sizeHint().height()
            self.stackedWidget.setFixedHeight(h)
    
    
    def main():
        app = QApplication(sys.argv)
        main_window = MainWindow()
        main_window.show()
    
        def onTimeout():
            sw = main_window.stackedWidget
            sw.setCurrentIndex((sw.currentIndex() + 1) % sw.count())
    
        # test
        from PyQt5.QtCore import QTimer
    
        timer = QTimer(timeout=onTimeout)
        timer.start(1000)
    
        sys.exit(app.exec_())
    
    
    if __name__ == "__main__":
        main()