使用 pyqt4 创建类信号

Posted

技术标签:

【中文标题】使用 pyqt4 创建类信号【英文标题】:Creating a class signal with pyqt4 【发布时间】:2014-08-22 14:06:08 【问题描述】:

有没有办法从 pyqt4 中的类方法创建信号,而不是总是使用实例方法?

我有一个包装类,用于包装和存储 QLineEdit 和 QCheckBox 组合之间的状态。该类将 QLineEdit 中的所有值汇总到一个类变量中。如果未选中 QCheckBox,则从总和中扣除相关行编辑的值。如果用户编辑 QLineEdit,则扣除旧值并添加新值。我想在每次从类级别更改时发出更新的值。

现在我正在做的是传入 QLineEdit 实例,我将值转储到其中并通过所有包装器实例连接它。

我想做的是让下面的代码 sn-p 工作。

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

【问题讨论】:

【参考方案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()

请注意,它使用了new style signals,这使得实现非常简单明了。

编辑:这就是你应该如何连接信号:

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

那么您的代码可能会失败,因为当 QLineEdit 为空时,您没有处理 float(line_edit.text()) 上的 ValueError

此外,您的程序中肯定存在一些功能问题,主要与您处理sum_valuesprevious_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_())

【讨论】:

您可能想看看我添加的最后一个示例。 我唯一不喜欢我的工作的一点是在我误入歧途时没有一位资深导师来帮助指导我。这正是我想要的,谢谢!在回答我的问题时帮助我找出新的信号/插槽样式的双倍积分。

以上是关于使用 pyqt4 创建类信号的主要内容,如果未能解决你的问题,请参考以下文章

在循环中连接 PyQt4 中的插槽和信号

PyQt4发射信号

PyQt4信号与槽

Python PyQt4 信号未触发连接方法

PyQt4:如何/何时从 QTabWidget 的子类发出自定义信号?

PyQt4 信号和槽 - QToolButton