【问题标题】:PyQt4 signals and slots with eventFilter带有 eventFilter 的 PyQt4 信号和槽
【发布时间】:2015-03-01 04:26:01
【问题描述】:

我无法接收从事件过滤器发送的信号。在下面的示例中,按钮按下的信号/插槽工作正常,并且焦点输出滤波器信号发出 OK。然而,焦点输出信号没有被拦截,插槽也没有触发。知道我做错了什么吗?

from PyQt4.QtCore import SIGNAL, QObject, QEvent
from PyQt4.QtGui import QApplication, QLabel, QWidget, QLineEdit, QPushButton, QTextEdit, QVBoxLayout

class SignalOnFocus(QWidget):
    def __init__(self):
        super(SignalOnFocus, self).__init__()
        layout = QVBoxLayout()
        self.label = QLabel("Type in some text then push button")
        self.inputLineEdit1 = QLineEdit()
        self.inputLineEdit1.setObjectName("inputLineEdit1")

        self.focusOutFilter = FocusOutFilter()
        self.inputLineEdit1.installEventFilter(self.focusOutFilter)
        self.connect(self.inputLineEdit1, SIGNAL("focus_out"),
                 self.focusLost)
        self.inputLineEdit2 = QLineEdit()
        self.inputLineEdit2.setObjectName("inputLineEdit2")
        self.mousePressedFilter = MousePressedFilter()
        self.inputLineEdit2.installEventFilter(self.mousePressedFilter)
        self.connect(self.inputLineEdit2, SIGNAL("mouse_clicked"), self.mouseClicked)
        self.button1 = QPushButton("Press me")
        self.button1.setObjectName("button1")
        self.connect(self.button1, SIGNAL("clicked()"), self.buttonPressed)
        self.textEdit = QTextEdit()
        layout.addWidget(self.label)
        layout.addWidget(self.inputLineEdit1)
        layout.addWidget(self.inputLineEdit2)
        layout.addWidget(self.button1)  
        layout.addWidget(self.textEdit)
        self.setLayout(layout)

    def mouseClicked(self):
        self.textEdit.append(" mouse clicked")

    def buttonPressed(self):
        self.textEdit.append(" button pressed")

    def focusLost(self):
        self.textEdit.append(" focus_out")

class MousePressedFilter(QObject):
    def eventFilter(self, widget, event):
        if event.type() == QEvent.MouseButtonPress:
            print("--eventFilter() mouse_clicked on "+str(widget.objectName()))
            self.emit(SIGNAL("mouse_clicked"))
            return False
        else:
            return False

class FocusOutFilter(QObject):
    def eventFilter(self, widget, event):
        if event.type() == QEvent.FocusOut:
            print("--eventFilter() focus_out on "+str(widget.objectName()))
            self.emit(SIGNAL("focus_out"))
            return False
        else:
            return False

if __name__ == "__main__":
    app = QApplication([])
    form = SignalOnFocus()
    form.show()
    app.exec_()

【问题讨论】:

    标签: python event-handling pyqt pyqt4 signals-slots


    【解决方案1】:

    过滤器对象正在发出信号,因此在连接它们时需要指定:

        self.connect(self.focusOutFilter, SIGNAL("focus_out"), self.focusLost)
        ...
        self.connect(self.mousePressedFilter, SIGNAL("mouse_clicked"), self.mouseClicked)
    

    但请认真考虑摆脱用于连接信号的那种丑陋的旧式语法。今年对 Qt4 的官方支持即将结束,PyQt5 已经彻底淘汰了旧式语法。

    使用new-style syntax,您的示例将如下所示:

    from PyQt4.QtCore import pyqtSignal, QObject, QEvent
    
    class SignalOnFocus(QWidget):
        def __init__(self):
            ...    
            self.focusOutFilter = FocusOutFilter()
            self.inputLineEdit1.installEventFilter(self.focusOutFilter)
            self.focusOutFilter.focusOut.connect(self.focusLost)
    
    class FocusOutFilter(QObject):
        focusOut = pyqtSignal()
    
        def eventFilter(self, widget, event):
            if event.type() == QEvent.FocusOut:
                print("--eventFilter() focus_out on " + widget.objectName())
                self.focusOut.emit()
    

    我希望你会同意它看起来更具可读性(并且更容易正确)。

    (另请注意,如果您将 Python 3 与 PyQt 一起使用,默认情况下,任何返回 QString 的 Qt 方法都是 automatically converted to a python string - 因此您无需使用 str 自己进行转换。

    【讨论】:

    • 我在运行 PyQt5 时遇到了同样的问题。问题:在您的示例代码(新语法)中,focusOutFilter 连接到inputLineEdit1 的位置是什么?你能扩展一下你的代码 sn-p 吗?
    • @nostradamus。我已经更新了我的答案。但请注意,并不是真的有必要拥有一个单独的过滤器类。 SignalOnFocus 类可以以完全相同的方式执行该角色。
    • 哦,我明白了,我们仍然需要self.inputLineEdit1.installEventFilter()。这很有帮助,非常感谢!
    猜你喜欢
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 2013-10-22
    相关资源
    最近更新 更多