在PyQt4 QComboBox中使用QCheckBox锁定选择
我正在开始用 PyQt4
写一个图形用户界面(GUI)。这是我第一次接触GUI(而且面向对象编程对我来说也有点新鲜)。这个GUI里会有4到5个 QComboBox
,因为需要做很多选择,我希望用户能锁定某个选择,这样后面就不会不小心改动了。对于一个QComboBox,我用下面的代码解决了这个问题:
import sys
from PyQt4 import QtGui, QtCore
class MyGui(QtGui.QWidget):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.resize(250, 50)
# vertical layout for widgets
self.vbox = QtGui.QVBoxLayout()
self.setLayout(self.vbox)
# Create a combo box with some choices
self.combo_color = QtGui.QComboBox()
self.vbox.addWidget(self.combo_color)
items = 'Red Yellow Purple'.split()
self.combo_color.addItems(items)
self.connect(self.combo_color, QtCore.SIGNAL('activated(QString)'), self.use_choice)
# add a checkbox next to the combobox which (un-)locks the the combo-choice
self.checkbox_color = QtGui.QCheckBox('Lock Choice', self)
self.vbox.addWidget(self.checkbox_color)
self.connect(self.checkbox_color, QtCore.SIGNAL('stateChanged(int)'), self.lock_choice)
def use_choice(self, text):
# do something very useful with the choice
print 'The current choice is: {choice}'.format(choice=text)
def lock_choice(self):
if self.checkbox_color.isChecked():
self.combo_color.setEnabled(False)
print 'Choice {choice} locked'.format(choice=self.combo_color.currentText())
else:
self.combo_color.setEnabled(True)
print 'Choice unlocked'
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mygui = MyGui()
mygui.show()
app.exec_()
这段代码能正常工作,但我对它的设计不太满意,因为 lock_choice
方法只能锁定 combo_color
的选择。如果我想对另一个QComboBox(比如 combo_name
)和一个QCheckBox(比如 checkbox_name
)做同样的事情,我就得在类的 __init__(self)
代码块里加上以下代码:
# create second combo box with some other choices
self.combo_name = QtGui.QComboBox()
self.vbox.addWidget(self.combo_name)
items = 'Bob Peter'.split()
self.combo_name.addItems(items)
self.connect(self.combo_name, QtCore.SIGNAL('activated(QString)'), self.use_choice)
# add a checkbox next to the combobox which (un-)locks the the combo-choice
self.checkbox_name = QtGui.QCheckBox('Lock Choice', self)
self.vbox.addWidget(self.checkbox_name)
self.connect(self.checkbox_name, QtCore.SIGNAL('stateChanged(int)'), self.lock_choice) # <-- obviously wrong, as it (un-)locks color choice at the moment
现在这两个QComboBox可以共享 use_choice()
方法,但它们不能共享 lock_choice()
方法,因为这两个复选框都锁定了颜色选择。我希望 checkbox_name
能锁定名称选择,而不想复制粘贴当前的 lock_choice()
方法并更改硬编码的组合框。我相信有简单的方法,比如把目标组合框传给这个方法,但我还不知道怎么做。希望能得到帮助!
2 个回答
最简单的解决办法就是使用 toggled 信号和 setDisabled 槽函数:
self.checkbox_color.toggled.connect(self.combo_color.setDisabled)
(顺便提一下,使用 新式语法 来连接信号时,代码看起来更简洁)。
还值得一提的是,你可以使用 lambda
来进行内联信号连接,像这样:
self.checkbox_color.toggled.connect(
lambda checked: self.combo_color.setDisabled(checked))
当没有方便的信号/槽配对时,这可能是最常见的解决方案(当然,部分函数也可以以不同的方式实现类似的效果)。
试试部分函数-
from functools import partial
在连接信号的时候,传入QWidget的名字:
self.connect(self.checkbox_color, QtCore.SIGNAL('stateChanged(int)'), partial(self.lock_choice, self.combo_color))
在你的方法里,你可以添加一个参数。
我们会在方法中添加一个参数,像下面这样,以处理我们通过上面的部分函数传递过来的QWidget(比如QComboBox)。
def lock_choice(self, combos):
if combos.isEnabled(True):
combos.setEnabled(False)
print 'Choice {choice} locked'.format(choice=combos.currentText())