17.QT-事件处理分析、事件过滤器、拖放事件
Qt事件處理介紹
- Qt平臺(tái)會(huì)將系統(tǒng)產(chǎn)生的消息轉(zhuǎn)換為Qt事件
- Qt事件是一個(gè)QEvent的對(duì)象
- Qt事件用來描述程序內(nèi)部或外部發(fā)生的動(dòng)作
- 任意的QObject對(duì)象都具備事件處理的能力
Qt常見的事件繼承圖如下:
?
?
- QInputEvent:用戶輸入事件
- QDropEvent:用戶拖放事件
- QPaintEvent:描述操作系統(tǒng)繪制GUI動(dòng)作的事件
- QCloseEvent:用戶關(guān)閉窗口事件
- QTimerEvent:計(jì)時(shí)器事件
?
事件處理方式順序
1.Qt事件產(chǎn)生后立即被分發(fā)到QWidget對(duì)象
2.QWidget中的event(QEvent*)進(jìn)行事件處理
3.event()根據(jù)事件類型調(diào)用不同的事件處理函數(shù)
4.在事件處理函數(shù)中發(fā)送Qt中預(yù)定義的信號(hào)
5.調(diào)用信號(hào)關(guān)聯(lián)的槽函數(shù)
?
以按鈕點(diǎn)擊為例,如下圖所示:
?
?
QPushButton事件處理總結(jié)
1.當(dāng)點(diǎn)擊按鈕后,將會(huì)觸發(fā)鼠標(biāo)事件
2.調(diào)用event(QEvent*)成員函數(shù)
3.調(diào)用mouseReleaseEvent(QMouseEvent*)成員函數(shù)
4.調(diào)用click()成員函數(shù)
5.觸發(fā)信號(hào)SIGNAL(clicked());
?
同樣,當(dāng)用戶點(diǎn)擊窗口的關(guān)閉按鈕時(shí),也會(huì)觸發(fā)closeEvent()事件函數(shù),該函數(shù)需要重寫,才能實(shí)現(xiàn)
參考示例:
void MainWindow::closeEvent(QCloseEvent *event) {if (maybeSave()) //如果還有需要保存的數(shù)據(jù){writeSettings();event->accept();} else //取消關(guān)閉窗口{event->ignore();}}類似的還有keyEvent()獲取鍵盤事件函數(shù), keyReleaseEvent()鍵盤按下事件函數(shù),enterEvent光標(biāo)進(jìn)入組件事件函數(shù), leaveEvent光標(biāo)離開組件事件函數(shù)等等。
?
其中QCloseEvent繼承與QEvent,在QEvent中常用成員函數(shù)有
void accept (); //接收者處理當(dāng)前事件void ignore (); //接收者忽略當(dāng)前事件,忽略后,事件可能傳遞給父組件bool isAccepted(); //判斷當(dāng)前事件是否被處理過?
當(dāng)使用ignore()處理事件時(shí),該事件可能會(huì)傳遞給其父組件對(duì)象繼續(xù)處理
步驟如下:
- 寫兩個(gè)類:?QMyWidget、QMyLineEdit(QMyLineEdit是QMyWidget的類成員)
- 通過QMyLineEdit來重寫LineEdit的keyReleaseEvent()鍵盤按下事件函數(shù)
- 通過QMyWidget來重寫QWidget的keyReleaseEvent()鍵盤按下事件函數(shù)
- 然后通過ignore()處理QMyLineEdit的keyReleaseEvent()事件函數(shù)
- 判斷是否會(huì)繼續(xù)執(zhí)行QMyWidget父組件的keyReleaseEvent()事件函數(shù)
QLineEdit.h如下所示:
#ifndef QMYLINEEDIT_H #define QMYLINEEDIT_H#include <QLineEdit> #include <QtGui>class QMyLineEdit : public QLineEdit {Q_OBJECTpublic:explicit QMyLineEdit(QWidget *parent = 0);void keyReleaseEvent( QKeyEvent * event ); };#endif // QMYLINEEDIT_H?
QLineEdit.cpp如下所示:
#include "QMyLineEdit.h"QMyLineEdit::QMyLineEdit(QWidget *parent) :QLineEdit(parent) {}void QMyLineEdit::keyReleaseEvent( QKeyEvent * event ) {qDebug()<<"QMyLineEdit::keyReleaseEvent";qDebug()<<"key value:"<< event->key(); event->ignore(); //忽略當(dāng)前事件 }?
QMyWidget.h如下所示:
#ifndef QMYWIDGET_H #define QMYWIDGET_H#include "QMyLineEdit.h" #include <QWidget>class QMyWidget : public QWidget {Q_OBJECTQMyLineEdit line;public:explicit QMyWidget(QWidget *parent = 0);void keyReleaseEvent( QKeyEvent * event );};#endif // QMYWIDGET_H?
QMyWidget.cpp如下所示:
#include "QMyWidget.h"QMyWidget::QMyWidget(QWidget *parent) :QWidget(parent),line(this) { }void QMyWidget::keyReleaseEvent( QKeyEvent * event ) {qDebug()<<"QMyWidget::keyReleaseEvent";qDebug()<<"key value:"<< event->key();QWidget::keyPressEvent(event); }?
main()函數(shù)如下所示:
int main(int argc, char *argv[]) {QApplication a(argc, argv);QMyWidget w;w.show();return a.exec(); }效果如下:
?
可以看到成員調(diào)用了event->ignore()函數(shù)忽略事件后,同樣也會(huì)繼續(xù)進(jìn)入QMyWidget類處理事件?
?
Qt中的事件過濾器
- 事件過濾器可以對(duì)需要的組件接收到的事件進(jìn)行過濾,以及監(jiān)控
- 任意的QObject對(duì)象都可以作為事件過濾器使用
- 事件過濾器的實(shí)現(xiàn),需要重寫eventFilter()函數(shù)
- 組件要想被監(jiān)控,則需要通過installEventFilter()安裝事件過濾器
- 事件過濾器能夠決定是否將事件轉(zhuǎn)發(fā)給組件對(duì)象,如下圖所示:
?
eventFilter函數(shù)體如下所示:
bool QObject::eventFilter ( QObject * watched, QEvent * event );// watched:代表被監(jiān)控的組件 event:代表要轉(zhuǎn)發(fā)的事件//返回true,表示該事件也被過濾掉(處理),無需再轉(zhuǎn)發(fā)了//返回false,則正常轉(zhuǎn)發(fā)給watched?
參考示例-實(shí)現(xiàn)文本框只允許輸入數(shù)字:
class MainWindow : public QMainWindow{public:MainWindow();protected:bool eventFilter(QObject *obj, QEvent *ev);private:QTextEdit *textEdit;};MainWindow::MainWindow(){textEdit = new QTextEdit;setCentralWidget(textEdit);textEdit->setAttribute(Qt::WA_InputMethodEnabled, false); //禁止中文輸入法textEdit->installEventFilter(this);}bool MainWindow::eventFilter(QObject *obj, QEvent *event){if (obj == textEdit){if (event->type() == QEvent::KeyPress){QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);qDebug() << "Ate key press" << keyEvent->key();switch(keyEvent->key()) //只接受0~9數(shù)字{case Qt::Key_0:case Qt::Key_1:case Qt::Key_2:case Qt::Key_3:case Qt::Key_4:case Qt::Key_5:case Qt::Key_6:case Qt::Key_7:case Qt::Key_8:case Qt::Key_9:return false;default:return true;}}else{return false;}}else{return QMainWindow::eventFilter(obj, event);}}?
用戶拖放事件
每個(gè)QWidget對(duì)象都能處理拖放事件
常用的拖放事件相關(guān)函數(shù)有:
void dragEnterEvent ( QDragEnterEvent * event ); //拖事件處理函數(shù) void dropEvent ( QDropEvent * event ) ; //放事件處理函數(shù)?
拖放事件所處理的數(shù)據(jù)是QMimeData類
- QMimeData類可以通過QDragEnterEvent?或者?QDropEvent?的成員函數(shù)QDropEvent()獲取
- QMimeData支持多種不同類型的文件數(shù)據(jù)
MIME類型常用處理函數(shù)如下所示:
?
拖放事件的步驟如下:
1.在構(gòu)造函數(shù)里通過setAcceptDrops(true)函數(shù),讓該組件能接受拖放事件
2.重寫dragEnterEvent(QDragEnterEvent*?event)函數(shù)并判斷MIME類型
? 如果是期待的類型,則調(diào)用event?->acceptProposedAction();
? 否則調(diào)用 : event ->ignore();
3.重寫dropEvent()函數(shù)并判斷MIME類型
? 如果是期待的類型,則獲取MIME數(shù)據(jù)并處理.
? 否則調(diào)用 : event ->ignore();
?
示例:
class MainWindow : public QMainWindow{ private:QTextEdit *textEdit;void dragEnterEvent(QDragEnterEvent *event);void dropEvent(QDropEvent *event);public:MainWindow();};MainWindow::MainWindow(){textEdit = new QTextEdit;setCentralWidget(textEdit);textEdit->setAttribute(Qt::WA_InputMethodEnabled, false) ;textEdit->installEventFilter(this);this->setAcceptDrops(true);}void MainWindow::dragEnterEvent(QDragEnterEvent *event) {if(event->mimeData()->hasUrls()) //判斷拖的類型{event->acceptProposedAction();}else{event->ignore();} }void MainWindow::dropEvent(QDropEvent *event) {if(event->mimeData()->hasUrls()) //判斷放的類型{textEdit->clear();QList<QUrl> List = event->mimeData()->urls();for(int i=0;i<List.length();i++){textEdit->insertPlainText(List[i].toLocalFile()+"\n");}}else{event->ignore();} }效果:
?
?
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)標(biāo)注文章來源,碼字很辛苦,若覺得文章不錯(cuò),不妨點(diǎn)個(gè)贊~
標(biāo)注出處在于:珍惜他人的碼字成果,并且文章有更新或者修改出錯(cuò)的地方,也能方便他人查找到
總結(jié)
以上是生活随笔為你收集整理的17.QT-事件处理分析、事件过滤器、拖放事件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++11的for
- 下一篇: QFile练习(20200213)