PyQt4信号和插槽eventFilter

问题描述:

我无法接收事件过滤器发送的信号。在下面的例子中,按下按钮的信号/插槽工作正常,并且焦点输出过滤器信号发出OK。然而,焦点输出信号不会被拦截,插槽也不会触发。任何想法我做错了什么?PyQt4信号和插槽eventFilter

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

过滤对象发出信号,所以这是你所需要的指定时,将它们连接起来:

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自己转换它)。

+0

我在这里运行PyQt5有同样的问题。问题:您的示例代码(新语法)中的哪个位置是连接到'inputLineEdit1'的'focusOutFilter'?你能扩展你的代码片段吗? – nostradamus

+0

@nostradamus。我已经更新了我的答案。但请注意,没有必要拥有单独的过滤器类。 'SignalOnFocus'类可以完全相同的方式执行该角色。 – ekhumoro

+0

哦,我明白了,我们仍然需要'self.inputLineEdit1.installEventFilter()'。这很有帮助,非常感谢! – nostradamus