类似于Python PyQt - Checkbox to uncheck all other checkboxes
我想有一个复选框
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableView, QGridLayout, QWidget, QCheckBox
from PyQt5.QtGui import QFont
from functools import partial
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.font = QFont("Helvetica", 9)
self.setFont(self.font)
self.showMaximized()
grid = QGridLayout()
self.setLayout(grid)
positions = [(i,j) for i in range(5) for j in range(5)]
print('\npostions: ', positions)
wordlist = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']
for position, wordlist in zip(positions, wordlist):
checkB =(QCheckBox(wordlist))
checkB.setStatusTip("Crawling best singals for "+wordlist+"." ) # set Statusbar
checkB.stateChanged.connect(partial(self.checkState, wordlist))
grid.addWidget(checkB, *position)
checkBoxNone = QCheckBox("None Selected")
checkBoxNone.setChecked(True)
checkBoxNone.stateChanged.connect(self.checkState)
grid.addWidget(checkBoxNone, 6, 1)
checkAll = QCheckBox("Select All")
checkAll.setChecked(False)
checkAll.stateChanged.connect(self.selectAll)
grid.addWidget(checkAll, 6, 2)
widget = QWidget()
widget.setLayout(grid)
self.setCentralWidget(widget)
self.statusBar().showMessage('Ready')
# Here are the problems.
# Is it because I have create checkboxes with a for loop?
def selectAll(self, state):
if state == Qt.Checked:
if self.sender() == MainWindow.checkAll:
MainWindow.checkB.setChecked(True)
def checkState(self, checktext, state):
if state == Qt.Checked:
print(checktext)
if self.sender() == MainWindow.checkBoxNone:
MainWindow.checkB.setChecked(False)
elif self.sender() == MainWindow.checkB:
MainWindow.checkBoxNone.setChecked(False)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle('Fusion')
mw = MainWindow()
如何通过此设置获取有效的代码?
您的代码存在各种问题。
MainWindow.checkB
,MainWindow.checkBoxNone
等。它们不存在。您应该使用instance属性,并使用self.checkB
;checkBoxNone = QCheckBox("None Selected")
应该为self.checkBoxNone = QCheckBox("None Selected")
,依此类推] >>checkBoxNone.stateChanged
连接到需要两个位置参数的函数,但是stateChanged()
只有一个(状态);没有复选框信号返回文本;stateChanged()
等),也不要像在代码中那样由于stateChanged信号而选中未选中的框(或相反的框),因为它会导致递归;要使其正常工作,您应该对创建的所有复选框都具有一定的引用,然后应用所需的状态,同时要非常小心地更改每个复选框的复选框状态。
在下面的示例中,如果未选中所有复选框,或者至少选中了一个,则“全选”和“不选”复选框会被部分选中。
self.checkBoxNone
就是说,让我告诉您,不建议使用复选框来做您正在做的事情,因为从视觉上和从交互的角度来看,这都是违反直觉的。最好使用一个按钮检查所有内容,而另一个按钮则取消选中。另外,在命名变量和属性时要小心。例如,
问题跟踪的重要方面。class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) grid = QGridLayout() # You *cannot* set a layout to a main window # self.setLayout(grid) positions = [(i,j) for i in range(5) for j in range(5)] wordlist = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y'] # use a list to keep a reference to all checkboxes self.checkBoxes = [] for position, wordlist in zip(positions, wordlist): checkB =(QCheckBox(wordlist)) checkB.setStatusTip("Crawling best singals for "+wordlist+"." ) # set Statusbar checkB.stateChanged.connect(self.checkStates) grid.addWidget(checkB, *position) self.checkBoxes.append(checkB) self.checkBoxNone = QCheckBox("Select none") self.checkBoxNone.setCheckState(Qt.Unchecked) self.checkBoxNone.stateChanged.connect( partial(self.selectBoxes, False)) grid.addWidget(self.checkBoxNone, 6, 1) self.checkBoxAll = QCheckBox("Select All") self.checkBoxAll.setCheckState(Qt.PartiallyChecked) self.checkBoxAll.stateChanged.connect( partial(self.selectBoxes, True)) grid.addWidget(self.checkBoxAll, 6, 2) widget = QWidget() widget.setLayout(grid) self.setCentralWidget(widget) self.statusBar().showMessage('Ready') def checkStates(self): states = [c.isChecked() for c in self.checkBoxes] # temporarily block signals so that there is no recursive calls self.checkBoxAll.blockSignals(True) self.checkBoxNone.blockSignals(True) # set the "select all" fully checked too if all boxes are checked, # otherwise make it partially checked self.checkBoxAll.setCheckState( Qt.Checked if all(states) else Qt.PartiallyChecked) # set the "select none" unchecked only if all boxes are unchecked, # otherwise make it partially checked self.checkBoxNone.setCheckState( Qt.Unchecked if not any(states) else Qt.PartiallyChecked) # unblock signals back self.checkBoxAll.blockSignals(False) self.checkBoxNone.blockSignals(False) def selectBoxes(self, state): for check in self.checkBoxes: check.blockSignals(True) check.setChecked(state) check.blockSignals(False) self.checkStates()
和checkAll
非常相似,但是它们引用两个截然不同的对象:一个复选框和一个函数;他们的名字也应该反映出这种差异。虽然不遵循此原则并不代表技术问题,但是当对象(功能,属性等)的数量随程序的增长而增加时,这可能会成为问题:使用清晰明了的名称可提高可读性(和心理参考),即开发和