PyQt: How to create a scrollable window
Asked Answered
R

4

10

I think it should be much easier to create a scrollable window in PyQt. I have a list of labels that goes out of the window and I would like to scroll down to view them. At the moment the code does not give me an error, but the window just doesn't appear:

class Example(QWidget):

    def __init__(self):
        super().__init__()

        layout = QVBoxLayout()

        lbl_arr = makeLabelArr()

        for i in range(1,8):
            qb = lbl_arr[i]
            # qb.setFixedWidth(300)
            layout.addWidget(qb)

        layout.setAlignment(Qt.AlignTop)

        scroll = QScrollArea()
        scroll.setWidget(self)
        scroll.setWidgetResizable(True)
        scroll.setFixedHeight(400)

        layout.addWidget(scroll)

        self.setLayout(layout)


        self.setGeometry(0, 0, 600, 220)
        self.setWindowTitle('SnP watchlist')

        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    #print(QDesktopWidget().availableGeometry())

    ex = Example()
    sys.exit(app.exec_())
Roadability answered 3/9, 2017 at 15:0 Comment(0)
E
11

Make the window itself a QScrollArea, like this:

class Window(QScrollArea):
    def __init__(self):
        super(Window, self).__init__()
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setAlignment(Qt.AlignTop)
        for index in range(100):
            layout.addWidget(QLabel('Label %02d' % index))
        self.setWidget(widget)
        self.setWidgetResizable(True)
Ealdorman answered 3/9, 2017 at 15:43 Comment(3)
I tried this without using a layout, but it's not working. Instead of inheriting from the "QMainWindow" class I created a "QWidget" object and passed that in every "Q" item I wanted to make. Example: pastebin.com/ZDKNXZPZ. Is this a wrong approach? I already created the window without a layout.Nighttime
@Nighttime Please ask a new question.Ealdorman
Can't do that. Thanks though.Nighttime
D
3

There is an example here: https://www.learnpyqt.com/tutorials/qscrollarea/

from PyQt5.QtWidgets import (QWidget, QSlider, QLineEdit, QLabel, QPushButton, QScrollArea,QApplication,
                             QHBoxLayout, QVBoxLayout, QMainWindow)
from PyQt5.QtCore import Qt, QSize
from PyQt5 import QtWidgets, uic
import sys


class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.scroll = QScrollArea()             # Scroll Area which contains the widgets, set as the centralWidget
        self.widget = QWidget()                 # Widget that contains the collection of Vertical Box
        self.vbox = QVBoxLayout()               # The Vertical Box that contains the Horizontal Boxes of  labels and buttons

        for i in range(1,50):
            object = QLabel("TextLabel: "+str(i))
            self.vbox.addWidget(object)

        self.widget.setLayout(self.vbox)

        #Scroll Area Properties
        self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(self.widget)

        self.setCentralWidget(self.scroll)

        self.setGeometry(600, 100, 1000, 900)
        self.setWindowTitle('Scroll Area Demonstration')
        self.show()

        return

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

if __name__ == '__main__':
    main()
Dirkdirks answered 5/4, 2021 at 8:30 Comment(0)
W
0

You should set layout after adding the scroll bar widget.

class Example(QWidget):

    def __init__(self):
        super().__init__()

        layout = QVBoxLayout()

        lbl_arr = makeArrayOfLabelsHTML()

        for i in range(1,8):
            qb = lbl_arr[i]
            layout.addWidget(qb)

        layout.setAlignment(Qt.AlignTop)

        scroll = QScrollArea()
        scroll.setWidget(self)
        scroll.setWidgetResizable(True)
        scroll.setFixedHeight(400)
        layout.addWidget(scroll)

        # set layout after adding scroll bar 
        self.setLayout(layout)

        self.setGeometry(0, 0, 600, 220)
        self.setWindowTitle('SnP watchlist')

        self.show()



if __name__ == '__main__':

        app = QApplication(sys.argv)
        #print(QDesktopWidget().availableGeometry())

        ex = Example()
        sys.exit(app.exec_())
Wotan answered 3/9, 2017 at 15:19 Comment(1)
thanks for this, but still, the window does not show up even though I do not receive errorsRoadability
N
0

This illustrates one way to do things

import sys 
from PyQt5 import QtWidgets, QtCore

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(600, 200)
        self.setWindowTitle('One way to do scrolling')
        
        def add_stuff():
            self.add_stuff()
        QtCore.QTimer.singleShot(500, add_stuff)

    def add_stuff(self):
        self.resize(1200, 800)
        
        # comment out these blocks, starting with the bottom one
        
        central_widget = QtWidgets.QFrame(self)
        self.setCentralWidget(central_widget)
        central_widget.setLayout(QtWidgets.QVBoxLayout(central_widget))
        central_widget.setStyleSheet('border: 5px solid green;')
        
        scroll_area = QtWidgets.QScrollArea()
        scroll_area.setWidgetResizable(True)
        central_widget.layout().addWidget(scroll_area)
        scroll_area.setStyleSheet('border: 5px solid blue;')
        
        main_panel = QtWidgets.QFrame(central_widget)
        main_panel.setStyleSheet('border: 5px solid red;')
        scroll_area.setWidget(main_panel)
        
        # the crucial line: without this, main_panel will just adapt
        # its size to its parent by default
        main_panel.setMinimumSize(600, 500)
        
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()        

Run this and then make the window smaller using your mouse.

It's also important to be aware that some components, such as QTableView and QTreeView, implement scrolling components automatically.

The main thing to understand is that the scrolling happens because the child becomes too big for its parent (and its parent has set up scrolling). setMinimumSize is a very unsubtle way to illustrate this constraint: normally the child of a scroll-enabled parent will contain certain subcomponents which at some point will have a size below which they can't be compressed... the configured layout object of the child will also play a role in determining the minimum dimensions of the child.

Nominative answered 8/6, 2023 at 18:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.