Qt 事件(event)

2018-10-05 14:51 更新

事件(event)

前面說了幾個標(biāo)準(zhǔn)對話框,下面不打算繼續(xù)說明一些組件的使用,因為這些使用很難講完,很多東西都是與實際應(yīng)用相關(guān)的。實際應(yīng)用的復(fù)雜性決定了我們根本不可能把所有組件的所有使用方法都說明白。這次來說說 Qt 相對高級一點的特性:事件。

事件(event)是有系統(tǒng)或者 Qt 本身在不同的時刻發(fā)出的。當(dāng)用戶按下鼠標(biāo),敲下鍵盤,或者是窗口需要重新繪制的時候,都會發(fā)出一個相應(yīng)的事件。一些事件是在對用戶操作做出響應(yīng)的時候發(fā)出,如鍵盤事件等;另一些事件則是由系統(tǒng)自動發(fā)出,如計時器事件。

一般來說,使用 Qt 編程時,我們并不會把主要精力放在事件上,因為在 Qt 中,需要我們關(guān)心的事件總會發(fā)出一個信號。比如,我們關(guān)心的是 QPushButton 的鼠標(biāo)點擊,但我們不需要關(guān)心這個鼠標(biāo)點擊事件,而是關(guān)心它的 clicked()信號。這與其他的一些框架不同:在 Swing 中,你所要關(guān)心的是JButton 的 ActionListener 這個點擊事件。

Qt 的事件很容易和信號槽混淆。這里簡單的說明一下,signal 由具體對象發(fā)出,然后會馬上交給由connect 函數(shù)連接的 slot 進(jìn)行處理;而對于事件,Qt 使用一個事件隊列對所有發(fā)出的事件進(jìn)行維護(hù),當(dāng)新的事件產(chǎn)生時,會被追加到事件隊列的尾部,前一個事件完成后,取出后面的事件進(jìn)行處理。但是,必要的時候,Qt 的事件也是可以不進(jìn)入事件隊列,而是直接處理的。并且,事件還可以使用“事件過濾器”進(jìn)行過濾??偟膩碚f,如果我們使用組件,我們關(guān)心的是信號槽;如果我們自定義組件,我們關(guān)心的是事件。因為我們可以通過事件來改變組件的默認(rèn)操作。比如,如果我們要自定義一個 QPushButton,那么我們就需要重寫它的鼠標(biāo)點擊事件和鍵盤處理事件,并且在恰當(dāng)?shù)臅r候發(fā)出 clicked()信號。

還記得我們在 main 函數(shù)里面創(chuàng)建了一個 QApplication 對象,然后調(diào)用了它的 exec()函數(shù)嗎?其實,這個函數(shù)就是開始 Qt 的事件循環(huán)。在執(zhí)行 exec()函數(shù)之后,程序?qū)⑦M(jìn)入事件循環(huán)來監(jiān)聽?wèi)?yīng)用程序的事件。當(dāng)事件發(fā)生時,Qt 將創(chuàng)建一個事件對象。Qt 的所有事件都繼承于 QEvent 類。在事件對象創(chuàng)建完畢后,Qt 將這個事件對象傳遞給 QObject 的 event()函數(shù)。event()函數(shù)并不直接處理事件,而是按照事件對象的類型分派給特定的事件處理函數(shù)(event handler)。關(guān)于這一點,我們會在以后的章節(jié)中詳細(xì)說明。

在所有組件的父類 QWidget 中,定義了很多事件處理函數(shù),如 keyPressEvent()、keyReleaseEvent()、mouseDoubleClickEvent()、mouseMoveEvent ()、mousePressEvent()、mouseReleaseEvent()等。這些函數(shù)都是 protected virtual 的,也就是說,我們應(yīng)該在子類中重定義這些函數(shù)。下面來看一個例子。

#include <QApplication> 
#include <QWidget> 
#include <QLabel> 
#include <QMouseEvent> 

class EventLabel : public QLabel 
{ 

protected: 
        void mouseMoveEvent(QMouseEvent *event); 
        void mousePressEvent(QMouseEvent *event); 
        void mouseReleaseEvent(QMouseEvent *event); 
}; 

void EventLabel::mouseMoveEvent(QMouseEvent *event) 
{ 
        this->setText(QString("<center><h1>Move: (%1, %2)</h1></center>") 
                                                        .arg(QString::number(event->x()), QString::number(event->y()))); 
} 

void EventLabel::mousePressEvent(QMouseEvent *event) 
{ 
        this->setText(QString("<center><h1>Press: (%1, %2)</h1></center>") 
                                                        .arg(QString::number(event->x()), QString::number(event->y()))); 
} 

void EventLabel::mouseReleaseEvent(QMouseEvent *event) 
{ 
        QString msg; 
        msg.sprintf("<center><h1>Release: (%d, %d)</h1></center>", 
                                event->x(), event->y()); 
        this->setText(msg); 
} 

int main(int argc, char *argv[]) 
{ 
        QApplication app(argc, argv); 
        EventLabel *label = new EventLabel; 
        label->setWindowTitle("MouseEvent Demo"); 
        label->resize(300, 200); 
        label->show(); 
        return app.exec(); 
}

這里我們繼承了 QLabel 類,重寫了 mousePressEvent、mouseMoveEvent 和 MouseReleaseEvent 三個函數(shù)。我們并沒有添加什么功能,只是在鼠標(biāo)按下(press)、鼠標(biāo)移動(move)和鼠標(biāo)釋放(release)時把坐標(biāo)顯示在這個 Label 上面。注意我們在 mouseReleaseEvent 函數(shù)里面有關(guān) QString 的構(gòu)造。我們沒有使用 arg 參數(shù)的方式,而是使用 C 語言風(fēng)格的 sprintf 來構(gòu)造 QString 對象,如果你對 C 語法很熟悉(估計很多 C++程序員都會比較熟悉的吧),那么就可以在 Qt 中試試熟悉的 C 格式化寫法啦!

本文出自 “豆子空間” 博客,請務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/194031

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號