博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
17.QT-事件处理分析、事件过滤器、拖放事件
阅读量:5302 次
发布时间:2019-06-14

本文共 5965 字,大约阅读时间需要 19 分钟。

Qt事件处理介绍

  • Qt平台会将系统产生的消息转换为Qt事件
  • Qt事件是一个QEvent的对象
  • Qt事件用来描述程序内部或外部发生的动作
  • 任意的QObject对象都具备事件处理的能力

Qt常见的事件继承图如下:

 

 

  • QInputEvent:用户输入事件
  • QDropEvent:用户拖放事件
  • QPaintEvent:描述操作系统绘制GUI动作的事件
  • QCloseEvent:用户关闭窗口事件
  • QTimerEvent:计时器事件

 

事件处理方式顺序

1.Qt事件产生后立即被分发到QWidget对象

2.QWidget中的event(QEvent*)进行事件处理

3.event()根据事件类型调用不同的事件处理函数

4.在事件处理函数中发送Qt中预定义的信号

5.调用信号关联的槽函数

 

以按钮点击为例,如下图所示:

 

 

QPushButton事件处理总结

1.当点击按钮后,将会触发鼠标事件

2.调用event(QEvent*)成员函数

3.调用mouseReleaseEvent(QMouseEvent*)成员函数

4.调用click()成员函数

5.触发信号SIGNAL(clicked());

 

同样,当用户点击窗口的关闭按钮时,也会触发closeEvent()事件函数,该函数需要重写,才能实现

参考示例:

void MainWindow::closeEvent(QCloseEvent *event){     if (maybeSave())                        //如果还有需要保存的数据     {         writeSettings();         event->accept();    }      else                                    //取消关闭窗口    {         event->ignore();    } }

类似的还有keyEvent()获取键盘事件函数, keyReleaseEvent()键盘按下事件函数,enterEvent光标进入组件事件函数, leaveEvent光标离开组件事件函数等等。

 

其中QCloseEvent继承与QEvent,在QEvent中常用成员函数有

void  accept ();    //接收者处理当前事件void  ignore ();    //接收者忽略当前事件,忽略后,事件可能传递给父组件bool isAccepted();  //判断当前事件是否被处理过

 

当使用ignore()处理事件时,该事件可能会传递给其父组件对象继续处理

步骤如下:

  • 写两个类: QMyWidget、QMyLineEdit(QMyLineEdit是QMyWidget的类成员)
  • 通过QMyLineEdit来重写LineEdit的keyReleaseEvent()键盘按下事件函数
  • 通过QMyWidget来重写QWidget的keyReleaseEvent()键盘按下事件函数
  • 然后通过ignore()处理QMyLineEdit的keyReleaseEvent()事件函数
  • 判断是否会继续执行QMyWidget父组件的keyReleaseEvent()事件函数

QLineEdit.h如下所示:

#ifndef QMYLINEEDIT_H#define QMYLINEEDIT_H#include 
#include
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(); //忽略当前事件}

 

QMyWidget.h如下所示:

#ifndef QMYWIDGET_H#define QMYWIDGET_H#include "QMyLineEdit.h"#include 
class QMyWidget : public QWidget{ Q_OBJECT QMyLineEdit 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()函数如下所示:

int main(int argc, char *argv[]){        QApplication a(argc, argv);        QMyWidget w;        w.show();        return a.exec();}

效果如下:

 

可以看到成员调用了event->ignore()函数忽略事件后,同样也会继续进入QMyWidget类处理事件 

 

Qt中的事件过滤器

  • 事件过滤器可以对需要的组件接收到的事件进行过滤,以及监控
  • 任意的QObject对象都可以作为事件过滤器使用
  • 事件过滤器的实现,需要重写eventFilter()函数
  • 组件要想被监控,则需要通过installEventFilter()安装事件过滤器
  • 事件过滤器能够决定是否将事件转发给组件对象,如下图所示:

 

eventFilter函数体如下所示:

bool QObject::eventFilter ( QObject * watched, QEvent * event );       // watched:代表被监控的组件  event:代表要转发的事件       //返回true,表示该事件也被过滤掉(处理),无需再转发了       //返回false,则正常转发给watched

 

参考示例-实现文本框只允许输入数字:

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
(event); qDebug() << "Ate key press" << keyEvent->key(); switch(keyEvent->key()) //只接受0~9数字 { 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); } }

 

用户拖放事件

每个QWidget对象都能处理拖放事件

常用的拖放事件相关函数有:

void  dragEnterEvent ( QDragEnterEvent * event );  //拖事件处理函数void dropEvent ( QDropEvent * event ) ;           //放事件处理函数

 

拖放事件所处理的数据是QMimeData类

  • QMimeData类可以通过QDragEnterEvent 或者 QDropEvent 的成员函数QDropEvent()获取
  • QMimeData支持多种不同类型的文件数据

MIME类型常用处理函数如下所示:

 

拖放事件的步骤如下:

1.在构造函数里通过setAcceptDrops(true)函数,让该组件能接受拖放事件

2.重写dragEnterEvent(QDragEnterEvent* event)函数并判断MIME类型

  如果是期待的类型,则调用event ->acceptProposedAction();

  否则调用 : event ->ignore();

3.重写dropEvent()函数并判断MIME类型

  如果是期待的类型,则获取MIME数据并处理.

  否则调用 : 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
List = event->mimeData()->urls(); for(int i=0;i
insertPlainText(List[i].toLocalFile()+"\n"); } } else { event->ignore(); }}

效果:

 

转载于:https://www.cnblogs.com/lifexy/p/8996425.html

你可能感兴趣的文章
电脑的自带图标的显示
查看>>
[转载] redis 的两种持久化方式及原理
查看>>
C++ 删除字符串的两种实现方式
查看>>
ORA-01502: 索引'P_ABCD.PK_WEB_BASE'或这类索引的分区处于不可用状态
查看>>
Java抽象类和接口的比较
查看>>
开发进度一
查看>>
MyBaits学习
查看>>
管道,数据共享,进程池
查看>>
CSS
查看>>
[LeetCode] 55. Jump Game_ Medium tag: Dynamic Programming
查看>>
[Cypress] Stub a Post Request for Successful Form Submission with Cypress
查看>>
程序集的混淆及签名
查看>>
判断9X9数组是否是数独的java代码
查看>>
00-自测1. 打印沙漏
查看>>
UNITY在VS中调试
查看>>
SDUTOJ3754_黑白棋(纯模拟)
查看>>
Scala入门(1)Linux下Scala(2.12.1)安装
查看>>
如何改善下面的代码 领导说了很耗资源
查看>>
Quartus II 中常见Warning 原因及解决方法
查看>>
php中的isset和empty的用法区别
查看>>