使用QCheckBox锁定PyQt4 QComboBox中的选项

时间:2014-10-17 15:06:43

标签: python user-interface pyqt4 qcombobox qcheckbox

我开始使用PyQt4编写GUI。这是我第一次使用GUI(而且oo编程对我来说有点新鲜)。该GUI的一部分将类似于QComboBox的4到5个实例。由于要做出很多选择,我希望用户能够锁定一个选项,以便以后不会无意间更改。对于一个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是硬编码的,只能锁定QComboBox 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 个答案:

答案 0 :(得分:1)

尝试部分功能 -

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())

答案 1 :(得分:1)

最简单的解决方案是将toggled信号与setDisabled插槽一起使用:

    self.checkbox_color.toggled.connect(self.combo_color.setDisabled)

(并注意new-style sytax在进行信号连接时有多清洁。)

还值得指出的是,您还可以使用lambda进行内联信号连接,如下所示:

    self.checkbox_color.toggled.connect(
        lambda checked: self.combo_color.setDisabled(checked))

当没有方便的信号/插槽配对时,这可能是最惯用的解决方案(当然,部分功能可以以不同的方式实现或多或少相同的事情)。