QRadioButton Widget#
keywords: QRadioButton, RadioButton, Radio Button
Radio Widget 是单选按钮控件. 可以提供一组选项, 但是只允许用户选择一个.
ratio_widget_1.py
1# -*- coding: utf-8 -*-
2
3"""
4演示如何使用 ratio. 并且演示了如何正确使用 ``QRadioButton.toggled`` 的 signal.
5"""
6
7import sys
8from PySide6 import QtCore, QtWidgets
9
10
11class MainWidget(QtWidgets.QWidget):
12 """
13 Ref:
14
15 - QRadioButton: https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QRadioButton.html
16 - QButtonGroup: https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QButtonGroup.html
17 """
18
19 def __init__(self, parent):
20 super().__init__(parent)
21 # define
22 # 在一个 parent 下的所有 Radio, 默认情况下都是 exclusive 的, 即只能有一个被选中.
23 # 如果你需要让在一个 parent 下的 Ratio 分组, 通常有两种做法:
24 # 1. 把他们放到另一个 widget 中
25 # 2. 使用 QButtonGroup
26 self.ratio_1_wgt = QtWidgets.QRadioButton("label 1-1", self)
27 self.ratio_1_wgt.toggled.connect(self.on_ratio_toggled_handler)
28 self.ratio_2_wgt = QtWidgets.QRadioButton("label 1-2", self)
29 self.ratio_2_wgt.toggled.connect(self.on_ratio_toggled_handler)
30
31 self.main_lay = QtWidgets.QHBoxLayout() # Horizontal Box layout
32 self.main_lay.addWidget(self.ratio_1_wgt)
33 self.main_lay.addWidget(self.ratio_2_wgt)
34 self.setLayout(self.main_lay)
35
36 @QtCore.Slot()
37 def on_ratio_toggled_handler(self):
38 """
39 在定义 check / uncheck 的 signal 的时候, 这里有个问题是你需要所有的 Radio 都有一个 signal
40 这会导致多次重复触发的问题. 因为你选择一个 ratio 的时候, 其他的 ratio 也会自动改变状态,
41 等于是所有 ratio 的 toggler 都触发了 signal, 这是不必要的. 正确的做法是先判断当前的
42 ratio button 是不是 checked, 如果不是 checked 就不要执行后面的逻辑.
43 """
44 radio_button: QtWidgets.QRadioButton = self.sender()
45 if radio_button.isChecked():
46 print(
47 f"{self.ratio_1_wgt.isChecked() = }, {self.ratio_2_wgt.isChecked() = }"
48 )
49
50
51class MainWindow(QtWidgets.QMainWindow):
52 def __init__(self):
53 super().__init__()
54 self.main_wgt = MainWidget(self)
55 self.setCentralWidget(self.main_wgt)
56 self.setGeometry(
57 int(screen_width * 0.25), # x, at 25% of screen width
58 int(screen_height * 0.25), # y, at 25% of screen height
59 int(screen_width * 0.5), # w, 50% screen width
60 int(screen_height * 0.5), # h, 50% screen height
61 )
62 self.setWindowTitle("ratio_widget")
63 self.show()
64
65
66if __name__ == "__main__":
67 app = QtWidgets.QApplication(sys.argv)
68 screen_width, screen_height = app.screens()[0].size().toTuple()
69 main = MainWindow()
70 sys.exit(app.exec())
ratio_widget_2.py
1# -*- coding: utf-8 -*-
2
3"""
4演示如何对 ratio button 进行分组, 使得在一个组内, 最多只能有一个 ratio button 可以被 check.
5你在 App 中可以看到, label 1-1 和 label 1-2 是一组, label 2-1 和 label 2-2 是一组.
6"""
7
8import sys
9from PySide6 import QtCore, QtWidgets
10
11
12class MainWidget(QtWidgets.QWidget):
13 """
14 Reference:
15
16 - QRadioButton: https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QRadioButton.html
17 - QButtonGroup: https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QButtonGroup.html
18 """
19
20 def __init__(self, parent):
21 super().__init__(parent)
22 # Define button group
23 # 注意 ``QButtonGroup`` 不是一个 widget, 它只是一个 container, 可以将里面的
24 self.button_group_1 = QtWidgets.QButtonGroup(self)
25 self.ratio_1_1_wgt = QtWidgets.QRadioButton("label 1-1", self)
26 self.ratio_1_1_wgt.toggled.connect(self.button_group_1_toggled_handler)
27 self.button_group_1.addButton(self.ratio_1_1_wgt)
28 self.ratio_1_2_wgt = QtWidgets.QRadioButton("label 1-2", self)
29 self.ratio_1_2_wgt.toggled.connect(self.button_group_1_toggled_handler)
30 self.button_group_1.addButton(self.ratio_1_2_wgt)
31
32 self.button_group_2 = QtWidgets.QButtonGroup(self)
33 self.ratio_2_1_wgt = QtWidgets.QRadioButton("label 2-1", self)
34 self.ratio_2_1_wgt.toggled.connect(self.button_group_2_toggled_handler)
35 self.button_group_2.addButton(self.ratio_2_1_wgt)
36 self.ratio_2_2_wgt = QtWidgets.QRadioButton("label 2-2", self)
37 self.ratio_2_2_wgt.toggled.connect(self.button_group_2_toggled_handler)
38 self.button_group_2.addButton(self.ratio_2_2_wgt)
39
40 self.main_lay = QtWidgets.QVBoxLayout() # Vertical Box layout
41
42 self.button_group_1_lay = QtWidgets.QHBoxLayout() # Horizontal Box layout
43 self.button_group_1_lay.addWidget(self.ratio_1_1_wgt)
44 self.button_group_1_lay.addWidget(self.ratio_1_2_wgt)
45 self.main_lay.addLayout(self.button_group_1_lay)
46
47 self.button_group_2_lay = QtWidgets.QHBoxLayout() # Horizontal Box layout
48 self.button_group_2_lay.addWidget(self.ratio_2_1_wgt)
49 self.button_group_2_lay.addWidget(self.ratio_2_2_wgt)
50 self.main_lay.addLayout(self.button_group_2_lay)
51
52 self.setLayout(self.main_lay)
53
54 def print_radio_button_status(self):
55 print(
56 f"label 1-1 = {self.ratio_1_1_wgt.isChecked()}, "
57 f"label 1-2 = {self.ratio_1_2_wgt.isChecked()}, "
58 f"label 2-1 = {self.ratio_2_1_wgt.isChecked()}, "
59 f"label 2-2 = {self.ratio_2_2_wgt.isChecked()}"
60 )
61
62 @QtCore.Slot()
63 def button_group_1_toggled_handler(self):
64 radio_button: QtWidgets.QRadioButton = self.sender()
65 if radio_button.isChecked():
66 self.print_radio_button_status()
67
68 @QtCore.Slot()
69 def button_group_2_toggled_handler(self):
70 radio_button: QtWidgets.QRadioButton = self.sender()
71 if radio_button.isChecked():
72 self.print_radio_button_status()
73
74
75class MainWindow(QtWidgets.QMainWindow):
76 def __init__(self):
77 super().__init__()
78 self.main_wgt = MainWidget(self)
79 self.setCentralWidget(self.main_wgt)
80 self.setGeometry(
81 int(screen_width * 0.25), # x, at 25% of screen width
82 int(screen_height * 0.25), # y, at 25% of screen height
83 int(screen_width * 0.5), # w, 50% screen width
84 int(screen_height * 0.5), # h, 50% screen height
85 )
86 self.setWindowTitle("ratio_widget")
87 self.show()
88
89
90if __name__ == "__main__":
91 app = QtWidgets.QApplication(sys.argv)
92 screen_width, screen_height = app.screens()[0].size().toTuple()
93 main = MainWindow()
94 sys.exit(app.exec())
ratio_widget_3.py
1# -*- coding: utf-8 -*-
2
3"""
4演示如何对 ratio button 进行分组, 使得在一个组内, 最多只能有一个 ratio button 可以被 check.
5你在 App 中可以看到, label 1-1 和 label 1-2 是一组, label 2-1 和 label 2-2 是一组.
6
7特殊的是, 在这个例子中, 我们用的是 ``QButtonGroup.buttonToggled`` 的 Signal. 在这个例子中
8我们发现该方法失败了, 因为在一个 QButtonGroup 有几个 radio, 当任何 radio 改变时, 这个
9Signal 就会被触发几次. 我们还是需要用 ``QRadioButton.toggled`` 的 Signal 来处理比较好.
10"""
11
12import sys
13from PySide6 import QtCore, QtWidgets
14
15
16class MainWidget(QtWidgets.QWidget):
17 """
18 Reference:
19
20 - QRadioButton: https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QRadioButton.html
21 - QButtonGroup: https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QButtonGroup.html
22 """
23
24 def __init__(self, parent):
25 super().__init__(parent)
26 # Define button group
27 # 注意 ``QButtonGroup`` 不是一个 widget, 它只是一个 container, 可以将里面的
28 self.button_group_1 = QtWidgets.QButtonGroup(self)
29 self.ratio_1_1_wgt = QtWidgets.QRadioButton("label 1-1", self)
30 self.button_group_1.addButton(self.ratio_1_1_wgt)
31 self.ratio_1_2_wgt = QtWidgets.QRadioButton("label 1-2", self)
32 self.button_group_1.addButton(self.ratio_1_2_wgt)
33 self.button_group_1.buttonToggled.connect(self.button_group_1_toggled_handler)
34
35 self.button_group_2 = QtWidgets.QButtonGroup(self)
36 self.ratio_2_1_wgt = QtWidgets.QRadioButton("label 2-1", self)
37 self.button_group_2.addButton(self.ratio_2_1_wgt)
38 self.ratio_2_2_wgt = QtWidgets.QRadioButton("label 2-2", self)
39 self.button_group_2.addButton(self.ratio_2_2_wgt)
40 self.button_group_2.buttonToggled.connect(self.button_group_2_toggled_handler)
41
42 self.main_lay = QtWidgets.QVBoxLayout() # Vertical Box layout
43
44 self.button_group_1_lay = QtWidgets.QHBoxLayout() # Horizontal Box layout
45 self.button_group_1_lay.addWidget(self.ratio_1_1_wgt)
46 self.button_group_1_lay.addWidget(self.ratio_1_2_wgt)
47 self.main_lay.addLayout(self.button_group_1_lay)
48
49 self.button_group_2_lay = QtWidgets.QHBoxLayout() # Horizontal Box layout
50 self.button_group_2_lay.addWidget(self.ratio_2_1_wgt)
51 self.button_group_2_lay.addWidget(self.ratio_2_2_wgt)
52 self.main_lay.addLayout(self.button_group_2_lay)
53
54 self.setLayout(self.main_lay)
55
56 def print_radio_button_status(self):
57 print(
58 f"label 1-1 = {self.ratio_1_1_wgt.isChecked()}, "
59 f"label 1-2 = {self.ratio_1_2_wgt.isChecked()}, "
60 f"label 2-1 = {self.ratio_2_1_wgt.isChecked()}, "
61 f"label 2-2 = {self.ratio_2_2_wgt.isChecked()}"
62 )
63
64 @QtCore.Slot()
65 def button_group_1_toggled_handler(self):
66 print("trigger button_group_1_toggled_handler")
67 button_group: QtWidgets.QButtonGroup = self.sender()
68 for radio_wgt in button_group.buttons():
69 if radio_wgt.isChecked():
70 self.print_radio_button_status()
71
72 @QtCore.Slot()
73 def button_group_2_toggled_handler(self):
74 print("trigger button_group_2_toggled_handler")
75 button_group: QtWidgets.QButtonGroup = self.sender()
76 for radio_wgt in button_group.buttons():
77 if radio_wgt.isChecked():
78 self.print_radio_button_status()
79
80
81class MainWindow(QtWidgets.QMainWindow):
82 def __init__(self):
83 super().__init__()
84 self.main_wgt = MainWidget(self)
85 self.setCentralWidget(self.main_wgt)
86 self.setGeometry(
87 int(screen_width * 0.25), # x, at 25% of screen width
88 int(screen_height * 0.25), # y, at 25% of screen height
89 int(screen_width * 0.5), # w, 50% screen width
90 int(screen_height * 0.5), # h, 50% screen height
91 )
92 self.setWindowTitle("ratio_widget")
93 self.show()
94
95
96if __name__ == "__main__":
97 app = QtWidgets.QApplication(sys.argv)
98 screen_width, screen_height = app.screens()[0].size().toTuple()
99 main = MainWindow()
100 sys.exit(app.exec())