事件Event
1、事件的概述
Qt 中所有事件類都繼承於QEvent。在事件對象創建完畢後,Qt 將這個事件對象傳遞給QObject的event()函數。event()函數並不直接處理事件,而是按照事件對象的類型分派給特定的事件處理函數(event handler)
用戶如果使用該事件? 由於事件函數是virtual 必須用戶實現
2、通過QLabel瞭解事件的操作
如果重寫QLabel事件 需要在自定義的label控件中實現 事件的重寫
在mylabel.h中修改如下:
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
//MyLabel 繼承於 QLabel 就可以在MyLabel類中 重寫 QLabel的事件
class MyLabel : public QLabel
{
Q_OBJECT
public:
explicit MyLabel(QWidget *parent = 0);
signals:
public slots:
};
#endif // MYLABEL_H
在mylabel.cpp修改如下:
#include "mylabel.h"
MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
{
}
提升label的類型 爲MyLabel
總結:如果想重寫 某個類的事件 一般情況 就要自定義一個類 繼承於該控件的類型
然後將控件的類 提升成 自定義的類 這樣我們就可以在自定義類中 重寫控件類型事件函數
3、重寫事件:
事件資料:
mylabel.h
mylabel.cpp
運行結果:
4、重寫鼠標按下事件:
mylabel.h
mylabel.cpp
5、獲取鼠標按下或移動的座標
6、查看的QMouseEvent的信息
7、判斷button的返回值:
8、判斷鼠標的哪個按鍵按下
運行結果:
9、判斷鼠標的座標
運行結果:
10、鼠標跟蹤:(用戶 不用按下鼠標 也可以獲得鼠標移動位置)
在QWidgetd的Public Functions中找到
11、只需要在MyLabel的構造函數中設置一下就行:
運行結果:
事件分發器
概述:
事件對象創建完畢後,Qt 將這個事件對象傳遞給QObject的event()函數。event()函數並不直接處理事件,而是將這些事件對象按照它們不同的類型,分發給不同的事件處理器(event handler)。
event()函數主要用於事件的分發
如果你希望在事件分發之前做一些操作,就可以重寫這個event()函數了。
1、如果傳入的事件已被識別並且處理,則需要返回 true,否則返回 false。如果返回值是 true,那麼 Qt 會認爲這個事件已經處理完畢,不會再將這個事件發送給其它對象,而是會繼續處理事件隊列中的下一事件。
2、在event()函數中,調用事件對象的accept()和ignore()函數是沒有作用的,不會影響到事件的傳播。
3、記得不關心的事件 記得用父類的事件分發器處理。
1、案例:在事件分發器中 處理鼠標單擊事件
1.1、重寫 分發器事件(MyLabel類中)
virtual bool event(QEvent *e)
1.2、判斷出事鼠標單擊:QEvent::MouseButtonPress
mylabel.h聲明重寫事件分發器
mylabel.cpp 重寫事件分發器
事件過濾器
概述:
通過前面的章節,我們已經知道,Qt 創建了QEvent事件對象之後,會調用QObject的event()函數處理事件的分發。顯然,我們可以在event()函數中實現攔截的操作。由於event()函數是 protected 的,因此,需要繼承已有類。如果組件很多,就需要重寫很多個event()函數。這當然相當麻煩,更不用說重寫event()函數還得小心一堆問題。好在 Qt 提供了另外一種機制來達到這一目的:事件過濾器
不想讓它繼續轉發,就返回 true,否則返回 false
在QObject類中Public Functions找到:
1、在MyLabel.cpp的構造函數中 加載 事件過濾器
2、重寫事件過濾器
在mylabel.h中聲明 事件過濾器函數
在mylabel.cpp中實現 事件過濾器函數
運行結果:
注意:
1、這種全局的事件過濾器將會在所有其它特性對象的事件過濾器之前調用。儘管很強大,但這種行爲會嚴重降低整個應用程序的事件分發效率。
2、事件過濾器和被安裝過濾器的組件必須在同一線程,否則,過濾器將不起作用。另外,如果在安裝過濾器之後,這兩個組件到了不同的線程,那麼,只有等到二者重新回到同一線程的時候過濾器纔會有效。