PyQt5使用QSettings保存QRadioButton状态无法正确持久化
问题原因
- QSettings值类型转换错误:Linux下QSettings默认使用ini格式存储配置,布尔值会被序列化为字符串
"true"/"false"存储,读取时默认返回字符串类型。你直接用bool()转换的话,非空字符串都会被转为True,哪怕是"false",导致原本应该为False的状态被错误设置为True,最终两个按钮都被设为选中。 - 组件添加顺序错误导致互斥规则未生效:QRadioButton的同组互斥特性,只有在多个按钮被添加到同一个父容器(这里是QGroupBox)之后才会生效。你的代码里先读取配置给两个单选按钮设置选中状态,之后才将按钮添加到QGroupBox的布局中,设置状态时互斥规则还没生效,完全可以出现两个按钮同时为True的情况。
- 缺少默认值配置:调用
QSettings.value()时如果对应key不存在,会返回None,你直接用bool()转换得到False,不符合你初始希望“Promote Pawn Using Popup Window”默认选中的逻辑。
解决方案
修复步骤
- 指定QSettings返回值类型:调用
value()方法时通过第三个参数type=bool让Qt自动完成正确的布尔类型转换,避免字符串转布尔的错误。 - 调整初始化顺序:先把单选按钮添加到QGroupBox的布局中,确保互斥规则生效后,再读取配置设置按钮状态。
- 添加默认值:读取配置时传入默认值,避免首次运行无配置时状态错误。
修正后的核心代码示例
import sys from PyQt5.QtCore import QSettings from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QGroupBox, QRadioButton class MyApp(QWidget): def __init__(self): super().__init__() self.oAutoPromoteRadioBtn = QRadioButton("Automatically Promote to Queen") self.oAutoPromoteRadioBtn.toggled.connect(self.on_selected) self.oUsePopupRadioBtn = QRadioButton("Promote Pawn Using Popup Window") self.oUsePopupRadioBtn.toggled.connect(self.on_selected) # 先完成布局添加,让单选按钮互斥规则先生效 oVertLayoutForRadioButtons = QVBoxLayout() oVertLayoutForRadioButtons.addWidget(self.oAutoPromoteRadioBtn) oVertLayoutForRadioButtons.addWidget(self.oUsePopupRadioBtn) self.groupbox = QGroupBox("Select pawn promotion method:") self.groupbox.setFixedWidth(300) self.groupbox.setFixedHeight(95) self.groupbox.setLayout(oVertLayoutForRadioButtons) self.oVertLayout = QVBoxLayout() self.oVertLayout.addWidget(self.groupbox) self.setLayout(self.oVertLayout) # 互斥生效后再读取配置设置状态,指定返回布尔类型、添加默认值 self.settings = QSettings('LoneProgrammer2', 'qsettingsTest1') self.settings.beginGroup("Promotion Dialog") auto_checked = self.settings.value('auto-promote radio button checked state', False, type=bool) popup_checked = self.settings.value('promote using popup radio button checked state', True, type=bool) # 按存储的状态设置即可,互斥生效不会出现同时选中 self.oAutoPromoteRadioBtn.setChecked(auto_checked) self.oUsePopupRadioBtn.setChecked(popup_checked) self.settings.endGroup() print('AT APP OPENING:') print('self.oAutoPromoteRadioBtn.isChecked() = ', self.oAutoPromoteRadioBtn.isChecked()) print('self.oUsePopupRadioBtn.isChecked() = ', self.oUsePopupRadioBtn.isChecked()) def on_selected(self): radio_button = self.sender() if radio_button.isChecked(): if radio_button.text() == 'Automatically Promote to Queen': print('set to auto-promote to queen') elif radio_button.text() == 'Promote Pawn Using Popup Window': print('set to promote pawn to queen using popup window') def closeEvent(self, event): self.settings.beginGroup("Promotion Dialog") self.settings.setValue('auto-promote radio button checked state', self.oAutoPromoteRadioBtn.isChecked()) self.settings.setValue('promote using popup radio button checked state', self.oUsePopupRadioBtn.isChecked()) self.settings.endGroup() print() print('AT APP CLOSE:') print('self.oAutoPromoteRadioBtn.isChecked() = ', self.oAutoPromoteRadioBtn.isChecked()) print('self.oUsePopupRadioBtn.isChecked() = ', self.oUsePopupRadioBtn.isChecked()) if __name__ == "__main__": app = QApplication(sys.argv) demo = MyApp() demo.show() sys.exit(app.exec_())
内容的提问来源于stack exchange,提问作者Sam Quintanar
相关产品推荐
相关产品推荐

