Блокировка выбора в PyQt4 QComboBox с использованием QCheckBox

Я начинаю писать графический интерфейс, используя PyQt4, Это мой первый опыт работы с GUI (а также oo-программирование для меня несколько ново). Часть этого графического интерфейса будет как от 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 жестко запрограммирован только для блокировки выбора 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 ответа

Решение

Попробуйте частичные функции

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

Простейшим решением было бы использовать переключаемый сигнал со слотом setDisabled:

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

(И обратите внимание, насколько чище синтаксис нового стиля при подключении сигналов).

Также стоит отметить, что вы также можете использовать lambda для выполнения встроенных сигнальных соединений, например:

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

Это, пожалуй, самое идиоматическое решение, когда нет удобных пар сигнал / слот (и, конечно, частичные функции могут достигать более или менее одного и того же по-разному).

Другие вопросы по тегам