多个单选按钮组链接,导致奇怪的行为
Multiple Radio button groups are linking, causing strange behavior
我的程序根据 SQL 数据动态生成表格。我在它们旁边制作了两个单选按钮和一个 QLineEdit 条目。当右侧的单选按钮被选中时,QLineEdit 被正确启用。问题来自单选按钮链接并导致它们之间的排他性操作。当程序启动时,它们看起来像这样:
然后当我单击第一个 "No" 时,它会改变我的预期并启用 QLineEdit。
现在我也想为 "Serial#: RC1" 单击 "No"。这是行为开始出错的地方。
单击“否”按钮并取消选择上面的所有行。
如果我尝试再次单击第一行的 "No",第二行的 "yes" 将取消选择。
最后,我可以单击 Selected 单选按钮并取消选择所有内容,直到只剩下一个活动的单选按钮。在这一点上,我只能选择这个按钮。单击取消选择的按钮将激活它并取消选择先前激活的按钮。
我通过将单选按钮放入 QButtonGroups 的辅助函数即时生成按钮。我认为这足以阻止这种行为,但我错了。
我想要的是每行上的单选按钮不响应其他行上其他单选按钮上的操作。
# !/user/bin/env python
import os
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class Radio(QDialog):
def __init__(self, app):
super(Radio, self).__init__()
self.bundle_dir = os.path.dirname(__file__)
gui_path = os.path.join(self.bundle_dir, 'ui', 'radio_bt_test.ui')
self.ui = uic.loadUi(gui_path, self)
self.num_of_row = 4
self.formLayout = self.findChild(QFormLayout, "formLayout")
self.radio_bt_lineEdit_connections = dict() # to help link the radio buttons and lineEdit
self.add_rows()
self.show()
def add_rows(self):
"""
Adds pairs of radio buttons with a lineEdit to each row of the form layout
:return:
"""
for i in range(self.num_of_row):
lbl = QLabel("Label#" + str(i))
hbox = QHBoxLayout()
buttons = self.new_radio_pair()
entry = self.new_entry("Value if No")
entry.setEnabled(False)
self.radio_bt_lineEdit_connections[buttons[-1]] = entry
# adding connection to dictionary for later event handling
buttons[-1].toggled.connect(self.radio_bt_changed)
for button in buttons:
hbox.addWidget(button)
hbox.addWidget(entry)
self.formLayout.addRow(lbl, hbox)
def new_radio_pair(self, texts=('Yes', 'No')) -> list:
"""
Makes a pair of radio buttons in a button group for creating data entries in "Part" grouping on the fly
:param texts: The texts that will go on the two buttons. The more texts that are added to make more radio buttons
:return: A list with QRadioButtons that are all part of the same QButtonGroup
"""
group = QButtonGroup()
buttons = []
for text in texts:
bt = QRadioButton(text)
bt.setFont(QFont('Roboto', 11))
if text == texts[0]:
bt.setChecked(True)
group.addButton(bt)
buttons.append(bt)
return buttons
def radio_bt_changed(self) -> None:
"""
Helps the anonymous radio buttons link to the anonymous QLineEdits that are made for data fields
:return: None
"""
sender = self.sender()
assert isinstance(sender, QRadioButton)
lineEdit = self.radio_bt_lineEdit_connections[sender]
assert isinstance(lineEdit, QLineEdit)
if sender.isChecked():
lineEdit.setEnabled(True)
else:
lineEdit.setEnabled(False)
lineEdit.clear()
def new_entry(self, placeholder_text: str = "") -> QLineEdit:
"""
Makes a new QLineEdit object for creating data entries in "Part" grouping on the fly
:return: A new QLineEdit with appropriate font and size policy
"""
entry = QLineEdit()
entry.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
entry.setFont(QFont('Roboto', 11))
entry.setStyleSheet("background-color: rgb(239, 241, 243);")
# with style sheets, past anything in here between the css tags
entry.setMaxLength(15)
entry.setPlaceholderText(placeholder_text)
return entry
def main():
app = QApplication(sys.argv)
radio = Radio(app)
sys.exit(app.exec())
main()
是否可能因为我声明了 QButtonGroup 然后忘记了它们?垃圾收集器是否会来清除它们,因为我没有分配变量,或者是否还有其他我遗漏的问题。
ui 是在 QtDesigner 上设计的,只是一个带有表单布局的对话框。
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>491</width>
<height>382</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(219, 221, 223);</string>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>80</x>
<y>40</y>
<width>301</width>
<height>291</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout"/>
</widget>
</widget>
<resources/>
<connections/>
</ui>
应该用来使行按钮独占的对象是 "group" 但这是一个局部变量,当 new_radio_pair 方法完成执行时被销毁,导致它不像以前那样表现想法。
解决方案是延长生命周期,为此有多种选择,例如将其作为 class 的属性,将其添加到容器中或 class 具有更长生命周期循环,或者在 QObjects 的情况下,将另一个 QObject 作为父级(如 self
)传递给它,它具有更长的生命周期,这是这种情况下的最佳解决方案:
group = QButtonGroup(<b>self</b>)
我的程序根据 SQL 数据动态生成表格。我在它们旁边制作了两个单选按钮和一个 QLineEdit 条目。当右侧的单选按钮被选中时,QLineEdit 被正确启用。问题来自单选按钮链接并导致它们之间的排他性操作。当程序启动时,它们看起来像这样:
然后当我单击第一个 "No" 时,它会改变我的预期并启用 QLineEdit。
现在我也想为 "Serial#: RC1" 单击 "No"。这是行为开始出错的地方。 单击“否”按钮并取消选择上面的所有行。
如果我尝试再次单击第一行的 "No",第二行的 "yes" 将取消选择。
最后,我可以单击 Selected 单选按钮并取消选择所有内容,直到只剩下一个活动的单选按钮。在这一点上,我只能选择这个按钮。单击取消选择的按钮将激活它并取消选择先前激活的按钮。
我通过将单选按钮放入 QButtonGroups 的辅助函数即时生成按钮。我认为这足以阻止这种行为,但我错了。 我想要的是每行上的单选按钮不响应其他行上其他单选按钮上的操作。
# !/user/bin/env python
import os
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class Radio(QDialog):
def __init__(self, app):
super(Radio, self).__init__()
self.bundle_dir = os.path.dirname(__file__)
gui_path = os.path.join(self.bundle_dir, 'ui', 'radio_bt_test.ui')
self.ui = uic.loadUi(gui_path, self)
self.num_of_row = 4
self.formLayout = self.findChild(QFormLayout, "formLayout")
self.radio_bt_lineEdit_connections = dict() # to help link the radio buttons and lineEdit
self.add_rows()
self.show()
def add_rows(self):
"""
Adds pairs of radio buttons with a lineEdit to each row of the form layout
:return:
"""
for i in range(self.num_of_row):
lbl = QLabel("Label#" + str(i))
hbox = QHBoxLayout()
buttons = self.new_radio_pair()
entry = self.new_entry("Value if No")
entry.setEnabled(False)
self.radio_bt_lineEdit_connections[buttons[-1]] = entry
# adding connection to dictionary for later event handling
buttons[-1].toggled.connect(self.radio_bt_changed)
for button in buttons:
hbox.addWidget(button)
hbox.addWidget(entry)
self.formLayout.addRow(lbl, hbox)
def new_radio_pair(self, texts=('Yes', 'No')) -> list:
"""
Makes a pair of radio buttons in a button group for creating data entries in "Part" grouping on the fly
:param texts: The texts that will go on the two buttons. The more texts that are added to make more radio buttons
:return: A list with QRadioButtons that are all part of the same QButtonGroup
"""
group = QButtonGroup()
buttons = []
for text in texts:
bt = QRadioButton(text)
bt.setFont(QFont('Roboto', 11))
if text == texts[0]:
bt.setChecked(True)
group.addButton(bt)
buttons.append(bt)
return buttons
def radio_bt_changed(self) -> None:
"""
Helps the anonymous radio buttons link to the anonymous QLineEdits that are made for data fields
:return: None
"""
sender = self.sender()
assert isinstance(sender, QRadioButton)
lineEdit = self.radio_bt_lineEdit_connections[sender]
assert isinstance(lineEdit, QLineEdit)
if sender.isChecked():
lineEdit.setEnabled(True)
else:
lineEdit.setEnabled(False)
lineEdit.clear()
def new_entry(self, placeholder_text: str = "") -> QLineEdit:
"""
Makes a new QLineEdit object for creating data entries in "Part" grouping on the fly
:return: A new QLineEdit with appropriate font and size policy
"""
entry = QLineEdit()
entry.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
entry.setFont(QFont('Roboto', 11))
entry.setStyleSheet("background-color: rgb(239, 241, 243);")
# with style sheets, past anything in here between the css tags
entry.setMaxLength(15)
entry.setPlaceholderText(placeholder_text)
return entry
def main():
app = QApplication(sys.argv)
radio = Radio(app)
sys.exit(app.exec())
main()
是否可能因为我声明了 QButtonGroup 然后忘记了它们?垃圾收集器是否会来清除它们,因为我没有分配变量,或者是否还有其他我遗漏的问题。
ui 是在 QtDesigner 上设计的,只是一个带有表单布局的对话框。
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>491</width>
<height>382</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(219, 221, 223);</string>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>80</x>
<y>40</y>
<width>301</width>
<height>291</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout"/>
</widget>
</widget>
<resources/>
<connections/>
</ui>
应该用来使行按钮独占的对象是 "group" 但这是一个局部变量,当 new_radio_pair 方法完成执行时被销毁,导致它不像以前那样表现想法。
解决方案是延长生命周期,为此有多种选择,例如将其作为 class 的属性,将其添加到容器中或 class 具有更长生命周期循环,或者在 QObjects 的情况下,将另一个 QObject 作为父级(如 self
)传递给它,它具有更长的生命周期,这是这种情况下的最佳解决方案:
group = QButtonGroup(<b>self</b>)