QScrollArea Widget#

keywords: QScrollArea, ScrollArea, Scroll Area

这是一个用于演示如何使用 QScrollArea 来创建一个可以滚动的区域.

有的时候一个窗口是无法放下所有的 Widget 的, 这时就要用到 QScrollArea 这个 Widget. QScrollArea 本质上是一个大小有限制的矩形区域, 里面的元素如果超过了这个区域则会自动出现滚动条. QScrollArea 在 GUI 中非常有用. 它不仅能滚动整个 App 的窗口, 也可以把作为一个小的滚动区域跟其他的 Widget 放在一起.

scroll_area_example_1.py
 1# -*- coding: utf-8 -*-
 2
 3"""
 4这是一个用于演示如何使用 ``QScrollArea`` 来创建一个可以滚动的区域的例子.
 5
 6在这个例子中我们的 App 的主窗口中只有一个 ``QScrollArea`` (scroll_area_wgt) Widget.
 7里面必须包含有且只有一个作为容器的 ``QWidget`` (scroll_area_content_wgt). 所有你想要放在
 8Scroll Area 中的 widget 都需要被添加到 scroll_area_content_wgt 的 Layout 中. 注意,
 9不是直接添加到 scroll_area_wgt 中. 最后调用 ``scroll_area_wgt.setWidget(scroll_area_content_wgt)``
10方法将 scroll_area_content_wgt 作为唯一的 widget 添加到 scroll_area_wgt 中既可.
11
12Reference:
13
14- https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QScrollArea.html
15"""
16
17from PySide6 import QtWidgets, QtCore
18
19
20class MainWindow(QtWidgets.QMainWindow):
21    def __init__(self):
22        super().__init__()
23
24        # Create a widget as a container for all other widgets in the scroll area
25        self.scroll_area_content_wgt = QtWidgets.QWidget(self)
26        self.scroll_area_content_wgt_lay = QtWidgets.QVBoxLayout()
27        # add lots of widgets to the scroll area content widget
28        n = 50
29        for i in range(1, 1 + n):
30            label_wgt = QtWidgets.QLabel(f"TextLabel {i}")
31            self.scroll_area_content_wgt_lay.addWidget(label_wgt)
32        self.scroll_area_content_wgt.setLayout(self.scroll_area_content_wgt_lay)
33
34        # Create a Scroll Area widget
35        self.main_wgt_scroll_area = QtWidgets.QScrollArea()
36
37        # You can configure Scroll Area behavior with the following methods
38        # self.main_wgt_scroll_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
39        # self.main_wgt_scroll_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
40        # self.main_wgt_scroll_area.setWidgetResizable(True)
41
42        # Set the scroll area content widget as the scroll area only contains one widget, which is the "label_list_wgt"
43        self.main_wgt_scroll_area.setWidget(self.scroll_area_content_wgt)
44
45        # ----------------------------------------------------------------------
46        # Set Window
47        # ----------------------------------------------------------------------
48        # The set the "main_wgt_scroll_area" as central widget in App window
49        self.setCentralWidget(self.main_wgt_scroll_area)
50
51        # Set window property
52        self.setGeometry(
53            int(screen_width * 0.25),  # x, at 25% of screen width
54            int(screen_height * 0.25),  # y, at 25% of screen height
55            int(screen_width * 0.5),  # w, 50% screen width
56            int(screen_height * 0.5),  # h, 50% screen height
57        )
58        self.setWindowTitle("Scroll Area Demonstration")
59        self.show()
60
61
62if __name__ == "__main__":
63    import sys
64
65    app = QtWidgets.QApplication(sys.argv)
66    screen_width, screen_height = app.screens()[0].size().toTuple()
67    main = MainWindow()
68    sys.exit(app.exec())
scroll_area_example_2.py
 1# -*- coding: utf-8 -*-
 2
 3"""
 4这个例子跟上一个例子的效果一摸一样, 不过我们对代码进行了一些设计, 使得代码更加清晰.
 5"""
 6
 7from PySide6 import QtWidgets
 8
 9
10class ScrollAreaContentWidget(QtWidgets.QWidget):
11    """
12    由于你必须为 Scroll Area 额外创建一个 Widget 作为容器, 并且 Scroll Area 的 Layout
13    其实是在这个容器中完成的, 所以我们单独为 Scroll Area 创建了一个类.
14    """
15
16    def __init__(self, parent):
17        super().__init__(parent)
18        self.main_lay = QtWidgets.QVBoxLayout()
19        n = 50
20        for i in range(1, 1 + n):
21            label_wgt = QtWidgets.QLabel(f"TextLabel {i}")
22            self.main_lay.addWidget(label_wgt)
23        self.setLayout(self.main_lay)
24
25
26class MainWidgetScrollArea(QtWidgets.QScrollArea):
27    """
28    由于我们的 App 窗口中有且只有一个 QScrollArea, 所以这个 MainWidget 就是 QScrollArea.
29    的子类.
30    """
31
32    def __init__(self, parent):
33        super().__init__(parent)
34        # Create a widget as a container for all other widgets in the scroll area
35        self.scroll_area_content_wgt = ScrollAreaContentWidget(self)
36        # Set the scroll area content widget as the scroll area only contains one widget, which is the "label_list_wgt"
37        self.setWidget(self.scroll_area_content_wgt)
38
39
40class MainWindow(QtWidgets.QMainWindow):
41    def __init__(self):
42        super().__init__()
43
44        self.set_widget()
45        self.set_window()
46
47    def set_widget(self):
48        self.main_wgt_scroll_area = MainWidgetScrollArea(self)
49
50    def set_window(self):
51        # set the "main_wgt_scroll_area" as central widget in App window
52        self.setCentralWidget(self.main_wgt_scroll_area)
53
54        # Set window property
55        self.setGeometry(
56            int(screen_width * 0.25),  # x, at 25% of screen width
57            int(screen_height * 0.25),  # y, at 25% of screen height
58            int(screen_width * 0.5),  # w, 50% screen width
59            int(screen_height * 0.5),  # h, 50% screen height
60        )
61        self.setWindowTitle("Scroll Area Demonstration")
62        self.show()
63
64
65if __name__ == "__main__":
66    import sys
67
68    app = QtWidgets.QApplication(sys.argv)
69    screen_width, screen_height = app.screens()[0].size().toTuple()
70    main = MainWindow()
71    sys.exit(app.exec())
scroll_area_example_3.py
 1# -*- coding: utf-8 -*-
 2
 3"""
 4这个例子跟上一个例子的效果一摸一样, 不过我们对代码进行了一些设计, 使得代码更加清晰.
 5"""
 6
 7from PySide6 import QtWidgets
 8
 9
10class ScrollAreaContentWidget(QtWidgets.QWidget):
11    """
12    由于你必须为 Scroll Area 额外创建一个 Widget 作为容器, 并且 Scroll Area 的 Layout
13    其实是在这个容器中完成的, 所以我们单独为 Scroll Area 创建了一个类.
14    """
15
16    def __init__(self, parent):
17        super().__init__(parent)
18        self.main_lay = QtWidgets.QVBoxLayout()
19        n = 50
20        for i in range(1, 1 + n):
21            label_wgt = QtWidgets.QLabel(f"TextLabel {i}")
22            self.main_lay.addWidget(label_wgt)
23        self.setLayout(self.main_lay)
24
25
26class MainWidgetScrollArea(QtWidgets.QScrollArea):
27    """
28    由于我们的 App 窗口中有且只有一个 QScrollArea, 所以这个 MainWidget 就是 QScrollArea.
29    的子类.
30    """
31
32    def __init__(self, parent):
33        super().__init__(parent)
34        # Create a widget as a container for all other widgets in the scroll area
35        self.scroll_area_content_wgt = ScrollAreaContentWidget(self)
36        # Set the scroll area content widget as the scroll area only contains one widget, which is the "label_list_wgt"
37        self.setWidget(self.scroll_area_content_wgt)
38
39
40class MainWindow(QtWidgets.QMainWindow):
41    def __init__(self):
42        super().__init__()
43
44        self.set_widget()
45        self.set_window()
46
47    def set_widget(self):
48        self.main_wgt_scroll_area = MainWidgetScrollArea(self)
49
50    def set_window(self):
51        # set the "main_wgt_scroll_area" as central widget in App window
52        self.setCentralWidget(self.main_wgt_scroll_area)
53
54        # Set window property
55        self.setGeometry(
56            int(screen_width * 0.25),  # x, at 25% of screen width
57            int(screen_height * 0.25),  # y, at 25% of screen height
58            int(screen_width * 0.5),  # w, 50% screen width
59            int(screen_height * 0.5),  # h, 50% screen height
60        )
61        self.setWindowTitle("Scroll Area Demonstration")
62        self.show()
63
64
65if __name__ == "__main__":
66    import sys
67
68    app = QtWidgets.QApplication(sys.argv)
69    screen_width, screen_height = app.screens()[0].size().toTuple()
70    main = MainWindow()
71    sys.exit(app.exec())
scroll_area_example_4.py
../../_images/nested-scroll-area.png
 1# -*- coding: utf-8 -*-
 2
 3"""
 4这个例子演示了如何把 ScrollArea 和其他的 Widget 结合起来放在一起. 使得不是整个窗口
 5都是滚动区域, 而是只有一部分是滚动区域.
 6
 7在这个例子中, 我们在 QScrollArea Widget 的上面和下面分别放了很多 QLabel Widget,
 8并且设定只有 QScrollArea 能够滚动.
 9
10这个例子沿用了上一个例子中的代码设计.
11"""
12
13from PySide6 import QtWidgets
14
15
16class ScrollAreaContentWidget(QtWidgets.QWidget):
17    """
18    由于你必须为 Scroll Area 额外创建一个 Widget 作为容器, 并且 Scroll Area 的 Layout
19    其实是在这个容器中完成的, 所以我们单独为 Scroll Area 创建了一个类.
20    """
21
22    def __init__(self, parent):
23        super().__init__(parent)
24        self.main_lay = QtWidgets.QVBoxLayout()
25        n = 50
26        for i in range(1, 1 + n):
27            label_wgt = QtWidgets.QLabel(f"TextLabel {i}")
28            self.main_lay.addWidget(label_wgt)
29        self.setLayout(self.main_lay)
30
31
32class MainWidget(QtWidgets.QWidget):
33    """
34    这是 App 主窗口中所有的 Widget 的容器.
35    """
36
37    def __init__(self, parent):
38        super().__init__(parent)
39        self.main_lay = QtWidgets.QVBoxLayout()
40
41        # before scroll area
42        for i in range(1, 1 + 10):
43            label_wgt = QtWidgets.QLabel(f"Before Text Label {i}")
44            self.main_lay.addWidget(label_wgt)
45
46        # Create a widget as a container for all other widgets in the scroll area
47        self.scroll_area_wgt = QtWidgets.QScrollArea()
48        self.scroll_area_content_wgt = ScrollAreaContentWidget(self)
49        self.scroll_area_wgt.setWidget(self.scroll_area_content_wgt)
50        self.main_lay.addWidget(self.scroll_area_wgt)
51
52        # after scroll area
53        for i in range(1, 1 + 10):
54            label_wgt = QtWidgets.QLabel(f"After Text Label {i}")
55            self.main_lay.addWidget(label_wgt)
56
57        self.setLayout(self.main_lay)
58
59
60class MainWindow(QtWidgets.QMainWindow):
61    def __init__(self):
62        super().__init__()
63
64        self.set_widget()
65        self.set_window()
66
67    def set_widget(self):
68        self.main_wgt = MainWidget(self)
69
70    def set_window(self):
71        self.setCentralWidget(self.main_wgt)
72
73        # Set window property
74        self.setGeometry(
75            int(screen_width * 0.25),  # x, at 25% of screen width
76            int(screen_height * 0.25),  # y, at 25% of screen height
77            int(screen_width * 0.5),  # w, 50% screen width
78            int(screen_height * 0.5),  # h, 50% screen height
79        )
80        self.setWindowTitle("Scroll Area Demonstration")
81        self.show()
82
83
84if __name__ == "__main__":
85    import sys
86
87    app = QtWidgets.QApplication(sys.argv)
88    screen_width, screen_height = app.screens()[0].size().toTuple()
89    main = MainWindow()
90    sys.exit(app.exec())