鍍金池/ 教程/ C/ 事件接收與忽略
Qt 容器和算法拾遺
自定義 model 之一
反走樣
Hello, world!
Qt 容器類之關(guān)聯(lián)存儲容器
QStringListModel
拖放技術(shù)之一
狀態(tài)欄
QTreeWidget
拖放技術(shù)之二
通用算法
event()
Qt 學(xué)習(xí)之路(18): Qt 標(biāo)準(zhǔn)對話框之 QInputDialog
Qt 容器類之遍歷器和隱式數(shù)據(jù)共享
QListWidget
Meta-Object 系統(tǒng)
事件接收與忽略
Qt 學(xué)習(xí)之路(tip): parent 參數(shù)
Qt 標(biāo)準(zhǔn)對話框之 QColorDialog
QPainter(續(xù))
國際化(下)
漸變填充
自定義委托
創(chuàng)建 shared library
model-view 架構(gòu)
Graphics View Framework
自定義拖放數(shù)據(jù)對象
QSortFilterProxyModel
國際化(上)
組件布局
自定義 Model 之三
事件過濾器
QDirModel
Hello, world!(續(xù))
Qt 標(biāo)準(zhǔn)對話框之 QFileDialog
自定義 model 之二
深入了解信號槽
坐標(biāo)變換
剪貼板操作
QTableWidget
QByteArray 和 QVariant
創(chuàng)建一個對話框(下)
Qt 學(xué)習(xí)之路(32): 一個簡易畫板的實(shí)現(xiàn)(Graphics View)
文本文件讀寫
自定義事件
編寫跨平臺的程序
MainWindow
初探信號槽
Qt 學(xué)習(xí)之路(17): Qt 標(biāo)準(zhǔn)對話框之 QMessageBox
繪圖設(shè)備
菜單和工具條(續(xù))
二進(jìn)制文件讀寫
QString
事件(event)
菜單和工具條
QPainter
Qt 容器類之順序存儲容器
進(jìn)程間交互
API 文檔的使用
創(chuàng)建一個對話框(上)
一個簡易畫板的實(shí)現(xiàn)(QWidget)

事件接收與忽略

本章內(nèi)容也是關(guān)于 Qt 事件?;蛟S這一章不能有一個完整的例子,因?yàn)閷τ谑录偸歉杏X很抽象,還是從底層上理解一下比較好的吧!

前面說到了事件的作用,下面來看看我們?nèi)绾蝸斫邮帐录??;貞浺幌虑懊娴拇a,我們在子類中重寫了事件函數(shù),以便讓這些子類按照我們的需要完成某些功能,就像下面的代碼:

void MyLabel::mousePressEvent(QMouseEvent * event)
{
        if(event->button() == Qt::LeftButton) {
                // do something
        } else {
                QLabel::mousePressEvent(event);
        }
}

上面的代碼和前面類似,在鼠標(biāo)按下的事件中檢測,如果按下的是左鍵,做我們的處理工作,如果不是左鍵,則調(diào)用父類的函數(shù)。這在某種程度上說,是把事件向上傳遞給父類去響應(yīng),也就是說,我們在子類中“忽略”了這個事件。

我們可以把 Qt 的事件傳遞看成鏈狀:如果子類沒有處理這個事件,就會繼續(xù)向其他類傳遞。其實(shí),Qt的事件對象都有一個 accept()函數(shù)和 ignore()函數(shù)。正如它們的名字,前者用來告訴 Qt,事件處理函數(shù)“接收”了這個事件,不要再傳遞;后者則告訴 Qt,事件處理函數(shù)“忽略”了這個事件,需要繼續(xù)傳遞,尋找另外的接受者。在事件處理函數(shù)中,可以使用 isAccepted()來查詢這個事件是不是已經(jīng)被接收了。

事實(shí)上,我們很少使用 accept()和 ignore()函數(shù),而是想上面的示例一樣,如果希望忽略事件,只要調(diào)用父類的響應(yīng)函數(shù)即可。記得我們曾經(jīng)說過,Qt 中的事件大部分是 protected 的,因此,重寫的函數(shù)必定存在著其父類中的響應(yīng)函數(shù),這個方法是可行的。為什么要這么做呢?因?yàn)槲覀儫o法確認(rèn)父類中的這個處理函數(shù)沒有操作,如果我們在子類中直接忽略事件,Qt 不會再去尋找其他的接受者,那么父類的操作也就不能進(jìn)行,這可能會有潛在的危險。另外我們查看一下 QWidget 的 mousePressEvent()函數(shù)的實(shí)現(xiàn):

void QWidget::mousePressEvent(QMouseEvent *event)
{
        event->ignore();
        if ((windowType() == Qt::Popup)) {
                event->accept();
                QWidget* w;
                while ((w = qApp->activePopupWidget()) && w != this){
                        w->close();
                        if (qApp->activePopupWidget() == w) // widget does not want to dissappear
                                w->hide(); // hide at least
                }
                if (!rect().contains(event->pos())){
                        close();
                }
        }
}

請注意第一條語句,如果所有子類都沒有覆蓋 mousePressEvent 函數(shù),這個事件會在這里被忽略掉,這暗示著這個組件不關(guān)心這個事件,這個事件就可能被傳遞給其父組件。

不過,事情也不是絕對的。在一個情形下,我們必須使用 accept()和 ignore()函數(shù),那就是在窗口關(guān)閉的時候。如果你在窗口關(guān)閉時需要有個詢問對話框,那么就需要這么去寫:

void MainWindow::closeEvent(QCloseEvent * event)
{
        if(continueToClose()) {
                event->accept();
        } else {
                event->ignore();
        }
}

bool MainWindow::continueToClose()
{
        if(QMessageBox::question(this,
                                            tr("Quit"),
                                            tr("Are you sure to quit this application?"),
                                            QMessageBox::Yes | QMessageBox::No,
                                            QMessageBox::No)
                == QMessageBox::Yes) {
                return true;
        } else {
                return false;
        }
}

這樣,我們經(jīng)過詢問之后才能正常退出程序。

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