在PyQt4 QComboBox中使用QCheckBox锁定选择

0 投票
2 回答
867 浏览
提问于 2025-04-28 03:33

我正在开始用 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 个回答

1

最简单的解决办法就是使用 toggled 信号和 setDisabled 槽函数:

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

(顺便提一下,使用 新式语法 来连接信号时,代码看起来更简洁)。

还值得一提的是,你可以使用 lambda 来进行内联信号连接,像这样:

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

当没有方便的信号/槽配对时,这可能是最常见的解决方案(当然,部分函数也可以以不同的方式实现类似的效果)。

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

撰写回答