Qt学习之路27--事件传递过程和事件过滤器

事件传递过程

这里写图片描述
在子组件中将事件进行处理后可能再将事件传递给父组件对象。
QEvent类是所有事件处理的父类

QEvent中的关键成员函数

–void ignore();
接收者忽略当前事件,但事件可能传递给父组件
–void accept();
接收者期望处理当前事件
–bool isAccept();
判断当前事件是否被处理

示例:事件处理的顺序

先构建一个自定义的MyLineEdit类,在类里重写event()和keyPressEvent()

MyLineEdit::MyLineEdit(QWidget *parent) : QLineEdit(parent)
{
}
bool MyLineEdit::event(QEvent* e)
{
   if( e->type() == QEvent::KeyPress )
   {
       qDebug() << "MyLineEdit::event";
   }
   return QLineEdit::event(e);//调用默认事件处理函数
}
void MyLineEdit::keyPressEvent(QKeyEvent* e)//键盘按键事件
{
    qDebug() << "MyLineEdit::keyPressEvent";
    QLineEdit::keyPressEvent(e);
    e->ignore();//当前对象忽略处理此事件,所以父组件对象进行事件处理函数的调用
}

Widget作为父组件,当子组件忽略事件处理时将会将事件传递到父组件进行处理。

Widget::Widget(QWidget *parent): QWidget(parent), LineEdit(this)//LineEdit设置父组件
{
}
bool Widget::event(QEvent* e)
{
    if(e->type() == QEvent::KeyPress)
    {
        qDebug() << "Widget::event";
    }
    return QWidget::event(e);
}
void Widget::keyPressEvent(QKeyEvent* e)
{
    qDebug() << "Widget::keyPressEvent";
    QWidget::keyPressEvent(e);
}

重写事件处理函数后,由系统发送来的系统消息就会由重写后的event函数处理,然后根据事件类型调用相应的事件处理函数。
当事件类型是按下键盘时触发调用MyLineEdit::keyPressEvent函数,由于调用了ignore()函数,它就会告诉应用程序当前事件没有被处理,所以就会传递给父组件去处理。
这里写图片描述
在执行了子组件(MyLineEdit对象)的事件处理函数时后又执行了父组件(Widget对象)的事件处理函数。

注意:如果我们希望父组件对象或其他来接着处理当前的事件,那么一定要调用ignore()函数。

事件过滤器

  • 事件过滤器可以对其他组件接收到的事件进行监控。
  • 任意的QObject对象都可以作为事件过滤器使用,QWidget对象也是一个QObject对象。
  • 事件过滤器需要重写eventFilter()函数。
  • 监控的意义在于可以将事件没收,用来定制一些有用的GUI效果。
  • 事件过滤器特点:
    这里写图片描述
  • 事件过滤器使用套路:判断某个对象,判断某种事件类型,调用默认处理函数。
    这里写图片描述

示例:事件过滤

Widget::Widget(QWidget *parent): QWidget(parent), LineEdit(this)
{
    LineEdit.installEventFilter(this);//安装事件过滤器
}
bool Widget::eventFilter(QObject* obj, QEvent* e)
{
    bool ret = true;
   if( (obj == &LineEdit) && (e->type() == QEvent::KeyPress) )
   {
       qDebug() << "Widget::eventFilter";
       QKeyEvent* evt = dynamic_cast<QKeyEvent*>(e);
       switch(evt->key())//只有数字才会被传递到组件对象
       {
       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:
           ret = false;
           break;
       default:
           break;
       }
   }
   else
   {
       ret = QWidget::eventFilter(obj, e);
   }
   return ret;
}

结果返回true表示事件已经被处理,不需要传递给obj对象(其中obj表示已经安装了事件过滤器的组件对象);返回false时需要传递到obj对象去进行处理。
只有按下的是数字,事件才会被传递给安装了事件过滤器的组件对象。

这里写图片描述

注意:
1、在使用事件过滤器之前一定要先安装过滤器到想要关注的组件对象。
2、只有当按下的是数字才会将事件发送到组件对象(当eventFilter返回false时发送事件到组件对象)。否则会将其没收,不会进行事件处理,如后三行的打印语句,并不包括事件处理函数里的打印语句,表明并没有进行事件处理。

小结

  • Qt应用程序有严格的事件处理顺序
  • Qt事件可能在处理后传递给父组件对象
  • 可以通过installEventFilter()函数安装事件管理器
  • 事件管理器可以对其它组件接收到的事件进行监控
  • 事件过滤器能决定是否将事件转发到组件对象
已标记关键词 清除标记
详细目录 1. 序 2. Qt 简介 3. Hello, world! 4. 信号槽 5. 自定义信号槽 6. Qt 模块简介 7. MainWindow 简介 8. 添加动作 9. 资源文件 10. 对象模型 11. 布局管理器 12. 菜单栏、工具栏和状态栏 13. 对话框简介 14. 对话框数据传递 15. 标准对话框 QMessageBox 16. 深入 Qt5 信号槽新语法 17. 文件对话框 18. 事件 19. 事件的接受与忽略 20. event() 21. 事件过滤器 22. 事件总结 23. 自定义事件 24. Qt 绘制系统简介 25. 画刷和画笔 26. 反走样 27. 渐变 28. 坐标系统 29. 绘制设备 30. Graphics View Framework 31. 贪吃蛇游戏(1) 32. 贪吃蛇游戏(2) 33. 贪吃蛇游戏(3) 34. 贪吃蛇游戏(4) 35. 文件 36. 二进制文件读写 37. 文本文件读写 38. 存储容器 39. 遍历容器 40. 隐式数据共享 41. model/view 架构 42. QListWidget、QTreeWidget 和 QTableWidget 43. QStringListModel 44. QFileSystemModel 45. 模型 46. 视图和委托 47. 视图选择 48. QSortFilterProxyModel 49. 自定义只读模型 50. 自定义可编辑模型 51. 布尔表达式树模型 52. 使用拖放 53. 自定义拖放数据 54. 剪贴板 55. 数据库操作 56. 使用模型操作数据库 57. 可视化显示数据库数据 58. 编辑数据库外键 59. 使用流处理 XML 60. 使用 DOM 处理 XML 61. 使用 SAX 处理 XML 62. 保存 XML 63. 使用 QJson 处理 JSON 64. 使用 QJsonDocument 处理 JSON 65. 访问网络(1) 66. 访问网络(2) 67. 访问网络(3) 68. 访问网络(4) 69. 进程 70. 进程间通信 71. 线程简介 72. 线程和事件循环 73. Qt 线程相关类 74. 线程和 QObject 75. 线程总结 76. QML 和 QtQuick 2 77. QML 语法 78. QML 基本元素 79. QML 组件 80. 定位器 81. 元素布局 82. 输入元素 其他文章 宏定义中的 do {…} while (0) C++:在堆上创建对象,还是在栈上?
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页