1

I'm using Pyside2 to create a simple UI. I'm very new to Qt (and Python in general). I have been able to make my scroll areas in Qt work with simpler setups, but I have not been able to get the following setup to show any scrollbar, nor does it let me resize my window. The height is always fixed.

I want everything within the main layout to be scrollable if the contents go beyond the screen/window boundaries.

I also don't want the Qt window to always have the height of the contents (I suspect this is because I haven't defined something properly in QVBoxLayout).

Thank you very much for any help and suggestions!

from PySide2 import QtWidgets

class Test:
    def __init__(self):
        self._window = QtWidgets.QMainWindow()
        self._widget = QtWidgets.QWidget()
        self._window.resize(200, 200)
        self._window.setWindowTitle('My Scrollbar Test')
        self._window.setCentralWidget(self._widget)

        # Create a box layout
        self._mainLayout = QtWidgets.QVBoxLayout(self._widget)
        self._mainLayout.setContentsMargins(0,0,0,0)
        self._mainLayout.setSpacing(0)

        self._widget.setLayout(self._mainLayout)

        # Create a scroll area
        self._scrollAreaWidget = QtWidgets.QScrollArea()

        # Assign a QWidget to the scroll widget
        self._contentWidget = QtWidgets.QWidget()
        self._scrollAreaWidget.setWidget(self._contentWidget)
        self._scrollAreaWidget.setWidgetResizable(True)

        self._layout = QtWidgets.QVBoxLayout(self._contentWidget)
        self._contentWidget.setLayout(self._layout)

        # Add tabs
        self._tabWidget = QtWidgets.QTabWidget()
        self._tabWidget.addTab(self.createTabOneLayout(), 'Test 1')
        self._tabWidget.addTab(self.createTabOneLayout(), 'Test 2')
        self._tabWidget.setTabPosition(QtWidgets.QTabWidget.East)
        self._layout.addWidget(self._tabWidget)

        # Add widget containing scroll area to the main layout
        self._mainLayout.addWidget(self._contentWidget)

        self._window.show()

    # Tab function
    def createTabOneLayout(self):
        self._newTab = QtWidgets.QWidget()
        self._tabLayout = QtWidgets.QVBoxLayout(self._newTab)       

        # Add buttons
        for a in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
            self._newButton = QtWidgets.QPushButton(a)
            self._newButton.setFixedSize(50,50)
            self._tabLayout.addWidget(self._newButton)

        return self._newTab

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    t = Test()
    sys.exit(app.exec_())
yuecake
  • 19
  • 2

1 Answers1

0

You should not add the self._contentWidget to the main layout, because that is part of the scroll area, you should add the scroll area to it instead.

You should add the following line:

self._mainLayout.addWidget(self._scrollAreaWidget)

and remove this:

self._mainLayout.addWidget(self._contentWidget)

Consider that your code is more complex than it should be:

  • if you only have one scroll area and no other "sibling" widget, you should set that as central widget;
  • if you only have one QTabWidget in the scroll area, you should set it as main widget for the scroll area;

Also consider that the PyQt convention is to use subclasses for the main widget (the top level window), so it's better to directly inherit from QMainWindow for your Test class. This makes the code more clean and also allows easier overriding of existing methods.

Also, if you have a function that dynamically creates new elements, setting instance attributes for them is completely useless (and might lead to confusion): the new widgets are created with a parent (or their ownership is taken by a parent), so there's no need for a persistent reference (self.someObject instead of a local someObject) that would be overwritten anyway whenever the function is called again. This is valid for both functions and for loops.

class Test(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(200, 200)
        self.setWindowTitle('My Scrollbar Test')

        # Create a scroll area
        self._scrollAreaWidget = QtWidgets.QScrollArea()
        self.setCentralWidget(self._scrollAreaWidget)

        # Add tabs
        self._tabWidget = QtWidgets.QTabWidget()
        self._tabWidget.addTab(self.createTabOneLayout(), 'Test 1')
        self._tabWidget.addTab(self.createTabOneLayout(), 'Test 2')
        self._tabWidget.setTabPosition(QtWidgets.QTabWidget.East)

        self._scrollAreaWidget.setWidget(self._tabWidget)
        self._scrollAreaWidget.setWidgetResizable(True)

        self.show()

    def createTabOneLayout(self):
        newTab = QtWidgets.QWidget()
        tabLayout = QtWidgets.QVBoxLayout(newTab)       

        # Add buttons
        for a in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
            newButton = QtWidgets.QPushButton(a)
            newButton.setFixedSize(50,50)
            tabLayout.addWidget(newButton)

        return newTab

musicamante
  • 41,230
  • 6
  • 33
  • 58