Создание сигнала класса с помощью pyqt4

Есть ли способ создать сигнал из метода класса в pyqt4, а не всегда использовать методы экземпляра?

У меня есть класс-оболочка, который упаковывает и сохраняет состояние между комбинацией QLineEdit и QCheckBox. Класс суммирует все значения в QLineEdit в переменной класса. Если флажок QCheckBox не установлен, значение редактирования соответствующей строки вычитается из суммы. Если пользователь редактирует QLineEdit, старое значение вычитается, а новое значение добавляется. Я хочу выдавать обновленное значение каждый раз, когда оно изменяется с уровня класса.

Прямо сейчас я передаю экземпляр QLineEdit, в который я выгружаю значение, и соединяю его со всеми экземплярами оболочки.

Я бы хотел, чтобы следующий фрагмент кода работал.

QtCore.QObject.connect(Wrapper,Wrapper.sum_values_signal, line_edit_instance.setText)

Однако это не так. Вот мой класс-оболочка для справки:

class Wrapper(QtCore.QObject):
    sum_values = 0
    sum_values_signal = QtCore.pyqtSignal(str)

    def __init__(self, line_edit, check_box):
        super(QtCore.QObject, self).__init__()
        self.check_box = check_box
        self.line_edit = line_edit

        Wrapper.sum_values += float(line_edit.text())
        self.previous_value = float(line_edit.text())

        QtCore.QObject.connect(self.check_box,
                               QtCore.SIGNAL(_fromUtf8("toggled(bool)")),
                               self.update_sum_values_wrt_check_box)

        QtCore.QObject.connect(self.line_edit,
                               QtCore.SIGNAL(_fromUtf8("textChanged(QString)")),
                               self.update_sum_values_wrt_line_edit)

    def update_sum_values_wrt_check_box(self, toggled):
        if toggled is False:
            Wrapper.sum_values -= self.previous_value
        else:
            Wrapper.sum_values += self.previous_value

        self.sum_values_signal.emit(text(Wrapper.sum_values))

    def update_sum_values_wrt_line_edit(self, string):
        Wrapper.sum_values -= self.previous_value
        Wrapper.sum_values += float(string)
        self.previous_value = float(string)
        self.sum_values_signal.emit(text(Wrapper.sum_values))

person Ben Hoff    schedule 22.08.2014    source источник


Ответы (1)


Чтобы определить собственный сигнал в классе, вам нужно использовать фабрика pyqtSignal. Вот простой пример:

class CustomWidget(QtGui.QWidget):

    # No argument signal
    custom_signal = QtCore.pyqtSignal()

    # Signal with int argument and a custom name
    custom_signal_int = QtCore.pyqtSignal(int, name='integerSignal')

    def atSomePointEvent(self, event):
        value = event.someValue()
        if isinstance(value, int):
            self.custom_signal_int.emit(value)
        else:
            self.custom_signal.emit()

Обратите внимание, что он использует сигналы нового стиля, которые делают реализацию действительно красивой и простой.

РЕДАКТИРОВАТЬ: Вот как вы должны подключать сигналы:

self.check_box.toggled.connect(self.check_box_toggled)
self.line_edit.textChanged.connect(self.line_edit_changed)  

Тогда ваш код, вероятно, потерпит неудачу, потому что вы не обрабатываете ValueError на float(line_edit.text()), когда QLineEdit пуст.

Кроме того, в вашей программе определенно есть некоторые функциональные проблемы, в основном связанные с тем, как вы обрабатываете sum_values и previous_value. Вы также можете избавиться от атрибута класса sum_value, так как это кажется неправильным выбором дизайна.

РЕДАКТИРОВАТЬ: Кстати, это то, что вы пытаетесь сделать?

from PyQt4 import QtCore, QtGui

class CustomLabel(QtGui.QLabel):

    def __init__(self, line_edit_lst):
        super(CustomLabel, self).__init__("0")
        self.line_edit_lst = line_edit_lst
        for line_edit in self.line_edit_lst:
            line_edit.textChanged.connect(self.update)

    def update(self, ignore):
        total = sum(self.str_to_float(line_edit.text())
                    for line_edit in self.line_edit_lst)
        self.setText(str(total))

    def str_to_float(self, string, default=0):
        try: return float(string)
        except ValueError: return default

class MyDialog(QtGui.QDialog):

    def __init__(self, parent=None):
        super(MyDialog, self).__init__(parent)
        hbox = QtGui.QVBoxLayout()
        self.lines = [QtGui.QLineEdit() for _ in range(5)]
        for line in self.lines:
            hbox.addWidget(line)
        self.label = CustomLabel(self.lines)
        hbox.addWidget(self.label)
        self.setLayout(hbox)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    w = MyDialog()
    w.show()
    sys.exit(app.exec_())
person Vincent    schedule 22.08.2014
comment
Возможно, вы захотите взглянуть на последний пример, который я добавил. - person Vincent; 22.08.2014
comment
Единственное, что мне не нравится в моей работе, это отсутствие старшего наставника, который помогал бы мне, когда я сбиваюсь с пути. Это именно то, что я искал, спасибо! Двойные баллы за помощь в понимании нового стиля сигналов/слотов при ответе на мой вопрос. - person Ben Hoff; 22.08.2014