上一篇提到提到了幾個元件綁定 Event 的方法,但那僅限與該 Object 提供給你用的事件,許多內建事件無法透過那些方法來監聽,例如 keyPressEvnet
、mouseButtonPress
等,就算有相應的事件可以用(例如 textChanged
、clicked
),通常也只能「後」處理而且也不一定完全對應(例如 textChanged
就無法偵測到 Ctrl、Alt 那些修飾按鍵)。如果硬要監聽該 Event 的話可能會這樣做:
self.b1.mouseButtonPress = self.myBtnClicked
然後你就發現原本註冊好的事件沒反應了,這個作法的缺點就是會覆蓋掉原本該事件的預設行為,而這預設行為通常也是大家對 GUI 期望的行為。又例如在文字列裡按鍵盤會有文字會跑出來,硬把 keyPressEvnet
改成自定義功能的話變成你要自己實作那些消失的功能。
有沒有一個方法可以讓我們單純監聽某事件,甚至還能控制該事件的觸發與否呢?
EventFilter
有,就是本篇要介紹的 EventFilter(事件過濾)。此內建 Method 就是在提供我們一條路可以單純只監聽事件而不影響其原生功能,該做的事情只要條件允許還是會做,另一方面只要我們想要也可以隨時取消該事件的觸發。
例如我想要監聽文字框 lEquation
,註冊的方法如下:
class Main(QtWidgets.QMainWindow, ui.Ui_MainWindow):
def __init__(self):
# ...
self.lEquation.installEventFilter(self)
def eventFilter(self, obj, event):
print(obj, event.type())
return False # will not be filtered out (ie. event will be processed)
就這麼簡單,請預設 return False
,否則所有事件都會被過濾掉,連 Paint(繪圖事件)都不例外於是就看不到元件了。
傳入的參數:
obj
可以讓你知道是誰被觸發了事件,同時註冊多個元件時才不會搞混event
就是該事件的完整訊息
那個 installEventFilter
的參數傳入的物件參數是一個類似漏斗的功能,雖然範例將之設定為自己但其實不限定。PyQt 會去 call 該漏斗物件的 evenrFilter
以達到事件過濾的功能,只要確保有實作此 Method 即可。
Reference