事件過濾器簡介在應(yīng)用中,,有時候一些事件并不是我們想要的,,這時候,,我們可以使用事件過濾器將不要的事件過濾掉,。在Qt中,,事件穿上到控件之前可以被攔截,,進入過濾,。這個功能可以讓我們編寫出更加個性化的事件處理,。 過濾器的實現(xiàn)方法: 重載eventFilter函數(shù),該函數(shù)形式為: QObject.eventFilter(self, watched :QObject, event:QEvent)
其中參數(shù)watched參數(shù)指要進行事件過濾的對象,, vent參數(shù)指要過濾的事件,。如果明確要過濾指定對象的指定事件,那么返回True,,否則返回False,。 安裝過濾器,讓相應(yīng)對象調(diào)用installEventFilter即可安裝過濾器,。如果不再需要這個過濾器,,可以調(diào)用removeEventFilter卸載掉。 注:一個對象可多次調(diào)用installEventFilter安裝多個過濾器,最后安裝的,,最先被調(diào)用,。也可將同一過濾器安裝到不同的對象。 注:事件過濾器會在內(nèi)置事件函數(shù)之前先捕獲相應(yīng)的事件,,如果該事件在eventFilter中被過濾了,,那么內(nèi)置事件函數(shù)將不會再進行響應(yīng),。比方說某個輸入框的鍵盤事件在eventFilter中被過濾了,那么被該輸入框的keyPressEvent()事件函數(shù)也就不會響應(yīng)了,。 事件過濾器演示在代碼中,,添加一個QPushButton按鈕用于安裝和卸載事件過濾器,一個QPlainTextEdit文本編輯框,,該控件作為過濾器演示對象,。 在eventFilter函數(shù)中,我們進行一個判斷,,如果對象是之前實例化好的文本編輯框,,而且是鍵盤事件的話,就返回True將這個事件給過濾掉,。注意未處理的事件必須返回給基類的eventFilter函數(shù),。 未安裝事件過濾器時,文本編輯框可以接收輸入文本,,安裝事件過濾器之后,,鍵盤事件被過濾,無法輸入任何文本,。 完整代碼如下: import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget,
QPushButton, QPlainTextEdit, QVBoxLayout,
QStatusBar)
class DemoEventFilter(QMainWindow):
def __init__(self, parent=None):
super(DemoEventFilter, self).__init__(parent)
# 設(shè)置窗口標(biāo)題
self.setWindowTitle('實戰(zhàn)PyQt5: 事件過濾器演示')
# 設(shè)置窗口大小
self.resize(400, 280)
self.initUi()
def initUi(self):
#狀態(tài)條
self.sBar = QStatusBar(self)
self.setStatusBar(self.sBar)
mainWidget = QWidget()
mainLayout = QVBoxLayout()
self.filterInstalled = False
self.btnSetFilter = QPushButton('安裝事件過濾器')
self.btnSetFilter.clicked.connect(self.onButtonSetFilter)
self.textEditor = QPlainTextEdit()
mainLayout.addWidget(self.btnSetFilter)
mainLayout.addWidget(self.textEditor)
mainWidget.setLayout(mainLayout)
self.setCentralWidget(mainWidget)
def onButtonSetFilter(self):
if not self.filterInstalled:
self.textEditor.installEventFilter(self)
self.btnSetFilter.setText('卸載事件過濾器')
self.filterInstalled = True
else:
self.textEditor.removeEventFilter(self)
self.btnSetFilter.setText('安裝事件過濾器')
self.filterInstalled = False
def eventFilter(self, watched, event):
if(watched == self.textEditor and event.type() == event.KeyPress):
self.sBar.showMessage('鍵盤事件被過濾', 500)
return True
return super(DemoEventFilter, self).eventFilter(watched, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DemoEventFilter()
window.show()
sys.exit(app.exec())
運行結(jié)果如下圖: 測試事件過濾器 全局過濾器演示可以將事件過濾器分離出來,,作為一個獨立的對象在全局中使用。下面的演示代碼中,,我們單獨在一個類里實現(xiàn)eventFilter事件過濾函數(shù),,過濾所有的鍵盤事件。在程序的入口處實例化鍵盤過濾器對象,,然后給三個不同類型的編輯框都安裝上該過濾器,。 完整代碼如下: import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QObject, pyqtSignal
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget,
QStatusBar, QVBoxLayout, QPushButton,
QPlainTextEdit, QLineEdit, QTextEdit)
class MyKeyPressFilter(QObject):
def __init__(self):
super(MyKeyPressFilter, self).__init__()
def eventFilter(self, watched, event):
if(event.type() == event.KeyPress):
print('鍵盤事件被過濾')
return True
return super(MyKeyPressFilter, self).eventFilter(watched, event)
class DemoGlobalFilter(QMainWindow):
def __init__(self, parent=None):
super(DemoGlobalFilter, self).__init__(parent)
# 設(shè)置窗口標(biāo)題
self.setWindowTitle('實戰(zhàn)PyQt5: 全局事件過濾器演示')
# 設(shè)置窗口大小
self.resize(400, 280)
self.initUi()
def initUi(self):
mainWidget = QWidget()
mainLayout = QVBoxLayout()
self.lineEditor = QLineEdit()
#安裝已創(chuàng)建的全局過濾器
self.lineEditor.installEventFilter(keypressFilter)
self.plainTextEditor = QPlainTextEdit()
#安裝已創(chuàng)建的全局過濾器
self.plainTextEditor.installEventFilter(keypressFilter)
self.textEditor = QTextEdit()
#安裝已創(chuàng)建的全局過濾器
self.textEditor.installEventFilter(keypressFilter)
mainLayout.addWidget(self.lineEditor)
mainLayout.addWidget(self.plainTextEditor)
mainLayout.addWidget(self.textEditor)
mainWidget.setLayout(mainLayout)
self.setCentralWidget(mainWidget)
if __name__ == '__main__':
#這里創(chuàng)建全局過濾器對象
keypressFilter = MyKeyPressFilter()
app = QApplication(sys.argv)
window = DemoGlobalFilter()
window.show()
sys.exit(app.exec())
運行結(jié)果如下圖: 測試全局事件過濾器 給QApplication安裝過濾器在前面的代碼中,每個控件都調(diào)用installEventFilter來安裝過濾器,,如果需要安裝過濾器的控件數(shù)量較多,,這樣操作就比較麻煩。一個簡單的處理辦法是給QApplication直接安裝事件過濾器,,這樣做的效果就是應(yīng)用中的每個控件對象都不會接收到被過濾的事件了,。如果我們想個別控件不受過濾器的影響,則可以修改eventFilter,加入判斷信息,,將不受過濾器影響的控件排除在外即可,。 演示程序代碼如下: import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QObject, pyqtSignal
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget,
QStatusBar, QVBoxLayout, QPushButton,
QPlainTextEdit, QLineEdit, QTextEdit)
class MyKeyPressFilter(QObject):
def __init__(self):
super(MyKeyPressFilter, self).__init__()
def eventFilter(self, watched, event):
if(event.type() == event.KeyPress):
print('鍵盤事件被過濾')
return True
return super(MyKeyPressFilter, self).eventFilter(watched, event)
class DemoGlobalFilter(QMainWindow):
def __init__(self, parent=None):
super(DemoGlobalFilter, self).__init__(parent)
# 設(shè)置窗口標(biāo)題
self.setWindowTitle('實戰(zhàn)PyQt5: QApplication 安裝過濾器演示')
# 設(shè)置窗口大小
self.resize(400, 280)
self.initUi()
def initUi(self):
mainWidget = QWidget()
mainLayout = QVBoxLayout()
self.lineEditor = QLineEdit()
self.plainTextEditor = QPlainTextEdit()
self.textEditor = QTextEdit()
mainLayout.addWidget(self.lineEditor)
mainLayout.addWidget(self.plainTextEditor)
mainLayout.addWidget(self.textEditor)
mainWidget.setLayout(mainLayout)
self.setCentralWidget(mainWidget)
if __name__ == '__main__':
#這里創(chuàng)建全局過濾器對象
keypressFilter = MyKeyPressFilter()
app = QApplication(sys.argv)
#注冊事件過濾器
app.installEventFilter(keypressFilter)
window = DemoGlobalFilter()
window.show()
sys.exit(app.exec())
運行結(jié)果同“全局過濾器演示”樣例。
|