W3Cschool
恭喜您成為首批注冊(cè)用戶(hù)
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
前面說(shuō)了幾個(gè)標(biāo)準(zhǔn)對(duì)話(huà)框,下面不打算繼續(xù)說(shuō)明一些組件的使用,因?yàn)檫@些使用很難講完,很多東西都是與實(shí)際應(yīng)用相關(guān)的。實(shí)際應(yīng)用的復(fù)雜性決定了我們根本不可能把所有組件的所有使用方法都說(shuō)明白。這次來(lái)說(shuō)說(shuō) Qt 相對(duì)高級(jí)一點(diǎn)的特性:事件。
事件(event)是有系統(tǒng)或者 Qt 本身在不同的時(shí)刻發(fā)出的。當(dāng)用戶(hù)按下鼠標(biāo),敲下鍵盤(pán),或者是窗口需要重新繪制的時(shí)候,都會(huì)發(fā)出一個(gè)相應(yīng)的事件。一些事件是在對(duì)用戶(hù)操作做出響應(yīng)的時(shí)候發(fā)出,如鍵盤(pán)事件等;另一些事件則是由系統(tǒng)自動(dòng)發(fā)出,如計(jì)時(shí)器事件。
一般來(lái)說(shuō),使用 Qt 編程時(shí),我們并不會(huì)把主要精力放在事件上,因?yàn)樵?Qt 中,需要我們關(guān)心的事件總會(huì)發(fā)出一個(gè)信號(hào)。比如,我們關(guān)心的是 QPushButton 的鼠標(biāo)點(diǎn)擊,但我們不需要關(guān)心這個(gè)鼠標(biāo)點(diǎn)擊事件,而是關(guān)心它的 clicked()信號(hào)。這與其他的一些框架不同:在 Swing 中,你所要關(guān)心的是JButton 的 ActionListener 這個(gè)點(diǎn)擊事件。
Qt 的事件很容易和信號(hào)槽混淆。這里簡(jiǎn)單的說(shuō)明一下,signal 由具體對(duì)象發(fā)出,然后會(huì)馬上交給由connect 函數(shù)連接的 slot 進(jìn)行處理;而對(duì)于事件,Qt 使用一個(gè)事件隊(duì)列對(duì)所有發(fā)出的事件進(jìn)行維護(hù),當(dāng)新的事件產(chǎn)生時(shí),會(huì)被追加到事件隊(duì)列的尾部,前一個(gè)事件完成后,取出后面的事件進(jìn)行處理。但是,必要的時(shí)候,Qt 的事件也是可以不進(jìn)入事件隊(duì)列,而是直接處理的。并且,事件還可以使用“事件過(guò)濾器”進(jìn)行過(guò)濾??偟膩?lái)說(shuō),如果我們使用組件,我們關(guān)心的是信號(hào)槽;如果我們自定義組件,我們關(guān)心的是事件。因?yàn)槲覀兛梢酝ㄟ^(guò)事件來(lái)改變組件的默認(rèn)操作。比如,如果我們要自定義一個(gè) QPushButton,那么我們就需要重寫(xiě)它的鼠標(biāo)點(diǎn)擊事件和鍵盤(pán)處理事件,并且在恰當(dāng)?shù)臅r(shí)候發(fā)出 clicked()信號(hào)。
還記得我們?cè)?main 函數(shù)里面創(chuàng)建了一個(gè) QApplication 對(duì)象,然后調(diào)用了它的 exec()函數(shù)嗎?其實(shí),這個(gè)函數(shù)就是開(kāi)始 Qt 的事件循環(huán)。在執(zhí)行 exec()函數(shù)之后,程序?qū)⑦M(jìn)入事件循環(huán)來(lái)監(jiān)聽(tīng)?wèi)?yīng)用程序的事件。當(dāng)事件發(fā)生時(shí),Qt 將創(chuàng)建一個(gè)事件對(duì)象。Qt 的所有事件都繼承于 QEvent 類(lèi)。在事件對(duì)象創(chuàng)建完畢后,Qt 將這個(gè)事件對(duì)象傳遞給 QObject 的 event()函數(shù)。event()函數(shù)并不直接處理事件,而是按照事件對(duì)象的類(lèi)型分派給特定的事件處理函數(shù)(event handler)。關(guān)于這一點(diǎn),我們會(huì)在以后的章節(jié)中詳細(xì)說(shuō)明。
在所有組件的父類(lèi) QWidget 中,定義了很多事件處理函數(shù),如 keyPressEvent()、keyReleaseEvent()、mouseDoubleClickEvent()、mouseMoveEvent ()、mousePressEvent()、mouseReleaseEvent()等。這些函數(shù)都是 protected virtual 的,也就是說(shuō),我們應(yīng)該在子類(lèi)中重定義這些函數(shù)。下面來(lái)看一個(gè)例子。
#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 類(lèi),重寫(xiě)了 mousePressEvent、mouseMoveEvent 和 MouseReleaseEvent 三個(gè)函數(shù)。我們并沒(méi)有添加什么功能,只是在鼠標(biāo)按下(press)、鼠標(biāo)移動(dòng)(move)和鼠標(biāo)釋放(release)時(shí)把坐標(biāo)顯示在這個(gè) Label 上面。注意我們?cè)?mouseReleaseEvent 函數(shù)里面有關(guān) QString 的構(gòu)造。我們沒(méi)有使用 arg 參數(shù)的方式,而是使用 C 語(yǔ)言風(fēng)格的 sprintf 來(lái)構(gòu)造 QString 對(duì)象,如果你對(duì) C 語(yǔ)法很熟悉(估計(jì)很多 C++程序員都會(huì)比較熟悉的吧),那么就可以在 Qt 中試試熟悉的 C 格式化寫(xiě)法啦!
本文出自 “豆子空間” 博客,請(qǐng)務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/194031
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話(huà):173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: