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
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())