不 同類型的事件,都有對應的事件處理函式,它們接受QEvent的特定子類別實例作為引數,像是下例中mousePressEvent()事件處理函式上的 QMouseEvent,您可以針對事件的某些狀況作特定處理,而其它未處理的狀況,則呼叫父類別對應的的事件處理函式,讓父類別預先定義的事件處理可以 完成:
void CustomLabel::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
// 處理左鍵按下
// ....
} else {
// 由父類別所定義的事件處理函式來事件
QLabel::mousePressEvent(event);
}
}
void CustomLabel::mouseReleaseEvent(QMouseEvent *event) {
// 滑鼠放開事件處理....
}
if (event->button() == Qt::LeftButton) {
// 處理左鍵按下
// ....
} else {
// 由父類別所定義的事件處理函式來事件
QLabel::mousePressEvent(event);
}
}
void CustomLabel::mouseReleaseEvent(QMouseEvent *event) {
// 滑鼠放開事件處理....
}
事實上,每個可傳播的事件都有accept()與igore()兩個方法,用以告知Qt應用程式,這個事件處理者是否接受或忽略此 一事件,如果事件處理者中呼叫事件的accept(),則事件不會再進一步傳播,若呼叫了ignore(),則Qt應用程式會嘗試尋找另一個事件的接受者,您可以藉由isAccepted()方法得知事件是否被接受。
一般來說,除了QCloseEvent之外,很少直接呼叫accept()或ignore(),如果您接受事件,則在事件處理者當中實作對事件的處理(如上例的if陳述句),如果您不 接受事件,則直接呼叫父類別的事件實作(如上例的else陳述句),對於QWidget來說,預設的實作是:
void QWidget::keyPressEvent(QKeyEvent *event) {
event->ignore();
}
event->ignore();
}
由於QWidget預設的實作是呼叫ignore(),這讓事件可以向父元件傳播。
QCloseEvent則建議直接呼叫accept()與ignore(),accept()方法會繼續關閉的操作,ignore()則會取消關閉的操作:
void MainWindow::closeEvent(QCloseEvent *event) {
if (continueToClose()) {
event->accept();
} else {
event->ignore();
}
}
if (continueToClose()) {
event->accept();
} else {
event->ignore();
}
}
QObject的event()方法通常用於分派事件,但在某些情況下,您希望在事件分派給其它事件處理者之 前,先行作一些處理,則可以重新定義event()方法,例如在視窗程式中,Tab鍵按下時希望其將焦點移至下一個圖型元件,而不是直接讓目前焦點的圖形 元件直接處理Tab鍵,則您可以在繼承QWidget子類別時,重新定義其event()方法,例如:
bool CustomWidget::event(QEvent *event) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Tab) {
// 處理Tab鍵
return true;
}
}
return QWidget::event(event);
}
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Tab) {
// 處理Tab鍵
return true;
}
}
return QWidget::event(event);
}
在執行時期想要知道所取得之QEvent類型,可以使用QEvent的type()方法取得常數值,並與QEvent::Type作比對。
事件若順利處理完畢,則要傳回true,表示這個事件被接受並處理,QApplication可以繼續事件佇列中的下一個事件處理,若傳回false,則QApplication嘗試尋找下一個可以處理事件的方法。 您不用呼叫事件的accept()或ignore(),這也沒有意義,accept()或ignore()是用來在特定的事件處理者之間作溝通,而 event()的true或false,是用來告知QApplication的notify()方法是否處理下一事件,以QWidget的event() 實作來說,它是根據事件的isAccepted()來判斷該傳回true或false:
bool QWidget::event(QEvent *event) {
switch (e->type()) {
case QEvent::KeyPress:
keyPressEvent((QKeyEvent *)event);
if (!((QKeyEvent *)event)->isAccepted())
return false;
break;
case QEvent::KeyRelease:
keyReleaseEvent((QKeyEvent *)event);
if (!((QKeyEvent *)event)->isAccepted())
return false;
break;
...
}
return true;
}
switch (e->type()) {
case QEvent::KeyPress:
keyPressEvent((QKeyEvent *)event);
if (!((QKeyEvent *)event)->isAccepted())
return false;
break;
case QEvent::KeyRelease:
keyReleaseEvent((QKeyEvent *)event);
if (!((QKeyEvent *)event)->isAccepted())
return false;
break;
...
}
return true;
}
另一個重新定義event()的情況是自訂QCustomEvent子類型時,您可以將之分派給其它函式或直接在event()中處理,例如:
bool CustomWidget::event(QEvent *event) {
if (event->type() == MyCustomEventType) {
CustomEvent *myEvent = static_cast<CustomEvent *>(event);
// 對自訂事件的處理,或呼叫其它函式來處理事件
return true;
}
return QWidget::event(event);
}
if (event->type() == MyCustomEventType) {
CustomEvent *myEvent = static_cast<CustomEvent *>(event);
// 對自訂事件的處理,或呼叫其它函式來處理事件
return true;
}
return QWidget::event(event);
}
自訂事件必須是QCustomEvent的子類別,您也可以直接實作customEvent()方法來處理自訂事件,詳可參考 自訂與傳送事件。