GroupBox 与 radioButtons 启用另一个 groupBox 不保持按钮状态
Posted
技术标签:
【中文标题】GroupBox 与 radioButtons 启用另一个 groupBox 不保持按钮状态【英文标题】:GroupBox with radioButtons enabling another groupBox doesn't keep button state 【发布时间】:2019-06-24 14:49:19 【问题描述】:我有三个 groupBox,每个都有两个单选按钮。第一个框中的按钮 启用/禁用第二个 groupBox。第二个按钮启用/禁用 第三组框。
这就是它应该的工作方式。
第二个和第三个 groupBoxes 默认是禁用的。 第一个框中的 radioButton 发送信号 toggled(bool) 以启用第二个 盒子。在那里,默认单击禁用第三个框的 radioButton,第二个 radioButton 向启用它的第三个框发送信号 toggled(bool)。
实际发生的是,当我启用第二个框时,第三个框 变为启用。当我在第二个框中切换按钮时,我可以启用/禁用第三个框,但是当我再次从第一个框禁用第二个框然后再次启用它时,无论在第二个框中单击哪个按钮,都会启用第三个框。
什么给了?
公平的游戏,这里有一个例子(我试图用 Designer 让它尽可能短)(imports, first class 和 'if name == ...' 在文件末尾包含额外的 4 个空格,以便代码显示为代码,删除它们以运行):
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox.setObjectName("groupBox")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox)
self.radioButton_2.setChecked(True)
self.radioButton_2.setObjectName("radioButton_2")
self.horizontalLayout_2.addWidget(self.radioButton_2)
self.radioButton = QtWidgets.QRadioButton(self.groupBox)
self.radioButton.setObjectName("radioButton")
self.horizontalLayout_2.addWidget(self.radioButton)
self.horizontalLayout_3.addLayout(self.horizontalLayout_2)
self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1)
self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox_2.setEnabled(False)
self.groupBox_2.setObjectName("groupBox_2")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_2)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox_2)
self.radioButton_3.setChecked(True)
self.radioButton_3.setObjectName("radioButton_3")
self.horizontalLayout_4.addWidget(self.radioButton_3)
self.radioButton_4 = QtWidgets.QRadioButton(self.groupBox_2)
self.radioButton_4.setObjectName("radioButton_4")
self.horizontalLayout_4.addWidget(self.radioButton_4)
self.horizontalLayout_5.addLayout(self.horizontalLayout_4)
self.gridLayout.addWidget(self.groupBox_2, 1, 0, 1, 1)
self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox_3.setEnabled(False)
self.groupBox_3.setObjectName("groupBox_3")
self.gridLayout.addWidget(self.groupBox_3, 2, 0, 1, 1)
self.horizontalLayout.addLayout(self.gridLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 30))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.radioButton.toggled['bool'].connect(self.groupBox_2.setEnabled)
self.radioButton_4.toggled['bool'].connect(self.groupBox_3.setEnabled)
self.radioButton_2.toggled['bool'].connect(self.groupBox_3.setDisabled)
self.radioButton_3.toggled['bool'].connect(self.groupBox_3.setDisabled)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.groupBox.setTitle(_translate("MainWindow", "whatever"))
self.radioButton_2.setText(_translate("MainWindow", "Off"))
self.radioButton.setText(_translate("MainWindow", "Sensors"))
self.groupBox_2.setTitle(_translate("MainWindow", "Control method"))
self.radioButton_3.setText(_translate("MainWindow", "On/Off"))
self.radioButton_4.setText(_translate("MainWindow", "PID"))
self.groupBox_3.setTitle(_translate("MainWindow", "PID settings"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
【问题讨论】:
也许这里有一个例子会有所帮助。见***.com/help/minimal-reproducible-example 【参考方案1】:首先(我的意思是最好的方式)这是一些非常丑陋的代码。我已经获取了您的代码并对其进行了清理,并在 Win10 上使用带有 pyqt5 的 Python 3.7 它运行良好,应该更容易理解。我希望这可以帮助您走上一条更有条理的发展道路。请记住,您经常需要返回并重新访问和/或重用您编写得最好的旧代码,以便以一种真正易于一目了然的方式编写它。
from sys import exit as sysExit
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class BoxOne(QGroupBox):
def __init__(self, CentrPane):
QGroupBox.__init__(self, CentrPane)
# Reference back to parent
self.CntrPane = CentrPane
self.setTitle('Main Controller')
self.radBtnOff = QRadioButton('Off')
self.radBtnOff.setChecked(True)
self.radBtnOff.toggled['bool'].connect(self.BoxTwoOff)
self.radBtnSnsr = QRadioButton('Sensors')
self.radBtnSnsr.toggled['bool'].connect(self.BoxTwoOn)
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.addWidget(self.radBtnOff)
self.horizontalLayout.addWidget(self.radBtnSnsr)
self.setLayout(self.horizontalLayout)
def BoxTwoOff(self):
# I assume you did not mean to leave Box Three Enabled
self.CntrPane.SecndBox.radBtnOnOff.setChecked(True)
self.CntrPane.SecndBox.setDisabled(True)
def BoxTwoOn(self):
self.CntrPane.SecndBox.setEnabled(True)
class BoxTwo(QGroupBox):
def __init__(self, CentrPane):
QGroupBox.__init__(self, CentrPane)
# Reference back to parent
self.CntrPane = CentrPane
self.setTitle('Control Method')
self.setEnabled(False)
self.radBtnOnOff = QRadioButton('On/Off')
self.radBtnOnOff.setChecked(True)
self.radBtnOnOff.toggled['bool'].connect(self.BoxThreeOff)
self.radBtnPID = QRadioButton('PID')
self.radBtnPID.toggled['bool'].connect(self.BoxThreeOn)
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.addWidget(self.radBtnOnOff)
self.horizontalLayout.addWidget(self.radBtnPID)
self.setLayout(self.horizontalLayout)
def BoxThreeOff(self):
self.CntrPane.ThirdBox.setDisabled(True)
def BoxThreeOn(self):
self.CntrPane.ThirdBox.setEnabled(True)
class BoxThree(QGroupBox):
def __init__(self, CentrPane):
QGroupBox.__init__(self, CentrPane)
# Reference back to parent
self.CntrPane = CentrPane
self.setTitle('PID Settings')
self.setEnabled(False)
self.MyEditor = QTextEdit('Editorial')
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.addWidget(self.MyEditor)
self.setLayout(self.horizontalLayout)
class CenterPanel(QWidget):
def __init__(self, MainWin):
QWidget.__init__(self)
# Reference back to parent
self.MainWin = MainWin
self.FirstBox = BoxOne(self)
self.SecndBox = BoxTwo(self)
self.ThirdBox = BoxThree(self)
self.gridLayout = QGridLayout()
self.gridLayout.addWidget(self.FirstBox, 0, 0, 1, 1)
self.gridLayout.addWidget(self.SecndBox, 1, 0, 1, 1)
self.gridLayout.addWidget(self.ThirdBox, 2, 0, 1, 1)
self.setLayout(self.gridLayout)
class MenuToolBar(QDockWidget):
def __init__(self, MainWin):
QDockWidget.__init__(self)
# Reference back to parent
self.MainWin = MainWin
self.MainMenu = MainWin.menuBar()
class StatusBar(QDockWidget):
def __init__(self, MainWin):
QDockWidget.__init__(self)
# Reference back to parent
self.MainWin = MainWin
self.MainMenu = MainWin.statusBar()
class UI_MainWindow(QMainWindow):
def __init__(self, AppDesktop):
super(UI_MainWindow, self).__init__(AppDesktop)
# Reference back to parent
self.MainDeskTop = AppDesktop
self.setWindowTitle('Main Window')
# Left, Top, Width, Height
self.setGeometry(200, 200, 800, 600)
self.CenterPane = CenterPanel(self)
self.setCentralWidget(self.CenterPane)
self.MenuToolBar = MenuToolBar(self)
self.StatusBar = StatusBar(self)
if __name__ == '__main__':
MainApp = QApplication([])
MainGui = UI_MainWindow(MainApp.desktop())
MainGui.show()
sysExit(MainApp.exec_())
【讨论】:
现在,这是一些非常漂亮的代码。感谢您花时间解开意大利面。我提供的代码是qt设计师吐出来的,不,不是我手写的……我认为按原样使用就可以了。除了通过设计器生成的代码很难看之外,请您尝试指出我做错了什么? 我的意思是:有没有办法在 qt5 设计器中实现这一点? 另外:理想情况下,当我启用第二个框,然后启用第三个框,然后禁用第二个框时,当我再次启用第二个框时,第三个框继续启用 - 就像上次一样当我们启用第二个框时。这样盒子就“记住”了它们的最后状态。这可行吗? 是的,设计师确实创建了一些非常丑陋的代码;)你出错的地方是使用设计师。我说有 2 个原因(第一个),正如您所知,它创建了一些非常丑陋的代码(第二个),您不了解事物如何交互,这意味着您尝试做的事情的实现将更加困难 至于使用 Designer 进行操作,我相信您可以 -- 不能说如何,因为坦率地说,我认为使用它没有任何意义,因为之后的维护是一场噩梦,我一直很担心这一点。跨度>以上是关于GroupBox 与 radioButtons 启用另一个 groupBox 不保持按钮状态的主要内容,如果未能解决你的问题,请参考以下文章
c# 在groupbox控件中判断的内嵌的radiobutton是不是已选