带事件过滤器的 PyQt4 信号和槽
PyQt4 signals and slots with eventFilter
我在接收事件过滤器发送的信号时遇到问题。在下面的示例中,按下的按钮 signal/slot 工作正常,聚焦输出滤波器信号发出 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_()
过滤器对象正在发出信号,因此这是您在连接它们时需要指定的内容:
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 一起使用,默认情况下,任何 returns a QString
是 automatically converted to a python string 的 Qt 方法 - 所以您不不需要使用 str
).
自行转换
我在接收事件过滤器发送的信号时遇到问题。在下面的示例中,按下的按钮 signal/slot 工作正常,聚焦输出滤波器信号发出 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_()
过滤器对象正在发出信号,因此这是您在连接它们时需要指定的内容:
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 一起使用,默认情况下,任何 returns a QString
是 automatically converted to a python string 的 Qt 方法 - 所以您不不需要使用 str
).