前面說了幾個標準對話框,下面不打算繼續說明一些組件的使用,由於這些使用很難講完,不少東西都是與實際應用相關的。實際應用的複雜性決定了咱們根本不可能把全部組件的全部使用方法都說明白。此次來講說Qt相對高級一點的特性:事件。
事件(event)是有系統或者Qt自己在不一樣的時刻發出的。當用戶按下鼠標,敲下鍵盤,或者是窗口須要從新繪製的時候,都會發出一個相應的事件。一些事件是在對用戶操做作出響應的時候發出,如鍵盤事件等;另外一些事件則是由系統自動發出,如計時器事件。
通常來講,使用Qt編程時,咱們並不會把主要精力放在事件上,由於在Qt中,須要咱們關心的事件總會發出一個信號。好比,咱們關心的是QPushButton的鼠標點擊,但咱們不須要關心這個鼠標點擊事件,而是關心它的clicked()信號。這與其餘的一些框架不一樣:在Swing中,你所要關心的是JButton的ActionListener這個點擊事件。
Qt的事件很容易和信號槽混淆。這裏簡單的說明一下,signal由具體對象發出,而後會立刻交給由connect函數鏈接的slot進行處理;而對於事件,Qt使用一個事件隊列對全部發出的事件進行維護,當新的事件產生時,會被追加到事件隊列的尾部,前一個事件完成後,取出後面的事件進行處理。可是,必要的時候,Qt的事件也是能夠不進入事件隊列,而是直接處理的。而且,事件還可使用「事件過濾器」進行過濾。總的來講,若是咱們
使用組件,咱們關心的是信號槽;若是咱們
自定義組件,咱們關心的是事件。由於咱們能夠經過事件來改變組件的默認操做。好比,若是咱們要自定義一個QPushButton,那麼咱們就須要重寫它的鼠標點擊事件和鍵盤處理事件,而且在恰當的時候發出clicked()信號。
還記得咱們在main函數裏面建立了一個QApplication對象,而後調用了它的exec()函數嗎?其實,這個函數就是開始Qt的事件循環。在執行exec()函數以後,程序將進入事件循環來監聽應用程序的事件。當事件發生時,Qt將建立一個事件對象。Qt的全部事件都繼承於QEvent類。在事件對象建立完畢後,Qt將這個事件對象傳遞給QObject的event()函數。event()函數並不直接處理事件,而是按照事件對象的類型分派給特定的事件處理函數(event handler)。關於這一點,咱們會在之後的章節中詳細說明。
在全部組件的父類QWidget中,定義了不少事件處理函數,如keyPressEvent()、keyReleaseEvent()、mouseDoubleClickEvent()、mouseMoveEvent ()、
mousePressEvent()、mouseReleaseEvent()等。這些函數都是protected virtual的,也就是說,咱們應該在子類中重定義這些函數。下面來看一個例子。
#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三個函數。咱們並無添加什麼功能,只是在鼠標按下(press)、鼠標移動(move)和鼠標釋放(release)時把座標顯示在這個Label上面。注意咱們在mouseReleaseEvent函數裏面有關QString的構造。咱們沒有使用arg參數的方式,而是使用C語言風格的sprintf來構造QString對象,若是你對C語法很熟悉(估計不少C+++程序員都會比較熟悉的吧),那麼就能夠在Qt中試試熟悉的C格式化寫法啦!