2015-01-02 281 views
0

我無法接收事件過濾器發送的信號。在下面的例子中,按下按鈕的信號/插槽工作正常,並且焦點輸出過濾器信號發出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_() 

回答

6

過濾對象發出信號,所以這是你所需要的指定時,將它們連接起來:

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