当前位置:   article > 正文

Qt中的事件处理_qt如何将系统消息转化为qt消息

qt如何将系统消息转化为qt消息

图形界面应用程序的消息处理模型

操作系统发送的消息如何转变为 Qt 信号?

Qt 平台将系统产生的消息转换为 Qt 事件

Qt 事件是一个 QEvent 对象

Qt 事件用于描述程序内部或外部发生的动作

任意的 QObject 对象都具有事件处理的能力

GUI 应用程序的事件处理方式

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())

自定义事件处理函数

QmyPushButton.h

  1. #ifndef QMYPUSHBUTTON_H
  2. #define QMYPUSHBUTTON_H
  3. #include <QWidget>
  4. #include <QPushButton>
  5. typedef void(QButtonListener)(QWidget *, QMouseEvent *);
  6. class QmyPushButton : public QPushButton
  7. {
  8. Q_OBJECT
  9. protected:
  10. QButtonListener* m_listen;
  11. /* 子类重写父类的虚函数 */
  12. void mouseReleaseEvent(QMouseEvent *e);
  13. public:
  14. explicit QmyPushButton(QWidget *parent = nullptr, QButtonListener *listen = nullptr);
  15. signals:
  16. };
  17. #endif // QMYPUSHBUTTON_H

QmyPushButton.cpp

  1. #include "QmyPushButton.h"
  2. #include <QMouseEvent>
  3. QmyPushButton::QmyPushButton(QWidget *parent, QButtonListener *listen) : QPushButton(parent)
  4. {
  5. m_listen = listen;
  6. }
  7. void QmyPushButton::mouseReleaseEvent(QMouseEvent *e)
  8. {
  9. if(m_listen != NULL)
  10. {
  11. m_listen(this, e);
  12. /* 标记当前的事件已经被处理 */
  13. e->accept();
  14. /* 设置按钮弹起 */
  15. setDown(false);
  16. }
  17. else
  18. {
  19. QPushButton::mouseReleaseEvent(e);
  20. }
  21. }

Widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QPushButton>
  5. #include "QmyPushButton.h"
  6. class Widget : public QWidget
  7. {
  8. Q_OBJECT
  9. private slots:
  10. void buttonClicked();
  11. private:
  12. QmyPushButton myButton;
  13. public:
  14. Widget(QWidget *parent = nullptr);
  15. ~Widget();
  16. };
  17. #endif // WIDGET_H

Widget.cpp

  1. #include "Widget.h"
  2. #include <QPushButton>
  3. #include <QDebug>
  4. #include <QMouseEvent>
  5. void func(QWidget *w, QMouseEvent *e)
  6. {
  7. qDebug() << "void func(QWidget *w, QMouseEvent *e)";
  8. }
  9. Widget::Widget(QWidget *parent)
  10. : QWidget(parent), myButton(this, func)
  11. {
  12. myButton.setText("myButton");
  13. connect(&myButton, &QPushButton::clicked, this, &Widget::buttonClicked);
  14. }
  15. void Widget::buttonClicked()
  16. {
  17. qDebug() << "void Widget::buttonClicked()";
  18. }
  19. Widget::~Widget()
  20. {
  21. }

当 QmyPushButton 被按下后松开后,会调用其 mouseReleaseEvent 函数。

事件 (Event) 和信号 (Signal) 不同

事件由具体对象进行处理

信号由具体对象主动产生

改写事件处理函数可能导致程序行为发生改变

信号是否存在对应的槽函数不会改变程序行为

一般而言,信号在具体的事件处理函数中产生

事件的传递过程

事件被组件对象处理后可能传递到其父组件对象

QEvent 中的关键成员函数

void ignore();

  • 接收者忽略当前事件,事件可能传递给父组件

void accept();

  • 接收者期望处理当前事件

bool isAccepted();

  • 判断当前事件是否被处理

事件处理的顺序

MyLineEdit.h

  1. #ifndef MYLINEEDIT_H
  2. #define MYLINEEDIT_H
  3. #include <QLineEdit>
  4. class MyLineEdit : public QLineEdit
  5. {
  6. Q_OBJECT
  7. protected:
  8. bool event(QEvent* e);
  9. void keyPressEvent(QKeyEvent* e);
  10. public:
  11. explicit MyLineEdit(QWidget* parent = nullptr);
  12. signals:
  13. };
  14. #endif // MYLINEEDIT_H

MyLineEdit.cpp

  1. #include "MyLineEdit.h"
  2. #include <QDebug>
  3. #include <QEvent>
  4. #include <QKeyEvent>
  5. MyLineEdit::MyLineEdit(QWidget *parent) : QLineEdit(parent)
  6. {
  7. }
  8. bool MyLineEdit::event(QEvent *e)
  9. {
  10. if(e->type() == QEvent::KeyPress)
  11. {
  12. qDebug() << "MyLineEdit::event";
  13. }
  14. return QLineEdit::event(e);
  15. }
  16. void MyLineEdit::keyPressEvent(QKeyEvent *e)
  17. {
  18. qDebug() << "MyLineEdit::keyPressEvent";
  19. QLineEdit::keyPressEvent(e);
  20. //e->ignore();
  21. }

Widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <MyLineEdit.h>
  5. #include <QEvent>
  6. class Widget : public QWidget
  7. {
  8. Q_OBJECT
  9. private:
  10. MyLineEdit myLineEdit;
  11. protected:
  12. bool event(QEvent *e);
  13. void keyPressEvent(QKeyEvent *e);
  14. public:
  15. Widget(QWidget *parent = nullptr);
  16. ~Widget();
  17. };
  18. #endif // WIDGET_H

Widget.cpp

  1. #include "Widget.h"
  2. #include <QDebug>
  3. #include <QEvent>
  4. #include <QKeyEvent>
  5. Widget::Widget(QWidget* parent)
  6. : QWidget(parent), myLineEdit(this)
  7. {
  8. }
  9. bool Widget::event(QEvent* e)
  10. {
  11. if(e->type() == QEvent::KeyPress)
  12. {
  13. qDebug() << "Widget::event";
  14. }
  15. return QWidget::event(e);
  16. }
  17. void Widget::keyPressEvent(QKeyEvent* e)
  18. {
  19. qDebug() << "Widget::keyPressEvent";
  20. QWidget::keyPressEvent(e);
  21. }
  22. Widget::~Widget()
  23. {
  24. }

在单行文本框输入字符时,首先会调用 Event 函数,接下来 Event 函数会调用 keyPressEvent 函数。

Qt 中的事件过滤器

事件过滤器可以对其它组件接收到的事件进行监控

任意的 QObject 对象都可以作为事件过滤器使用

事件过滤器需要重写 eventFilter() 函数

组件通过 installEventFilter() 函数安装事件过滤器

  • 事件过滤器在组件之前接收到事件
  • 事件过滤器能够决定是否将事件转发到组件对象

事件过滤器的典型实现 

事件过滤器的使用

Widget.cpp

  1. #include "Widget.h"
  2. #include <QDebug>
  3. #include <QEvent>
  4. #include <QKeyEvent>
  5. Widget::Widget(QWidget* parent)
  6. : QWidget(parent), myLineEdit(this)
  7. {
  8. myLineEdit.installEventFilter(this);
  9. }
  10. bool Widget::eventFilter(QObject* obj, QEvent* e)
  11. {
  12. bool ret = true;
  13. if((obj == &myLineEdit) && (e->type() == QEvent::KeyPress))
  14. {
  15. qDebug() << "Widget::eventFilter";
  16. QKeyEvent* key = dynamic_cast<QKeyEvent*>(e);
  17. switch(key->key())
  18. {
  19. case Qt::Key_0:
  20. case Qt::Key_1:
  21. case Qt::Key_2:
  22. case Qt::Key_3:
  23. case Qt::Key_4:
  24. case Qt::Key_5:
  25. case Qt::Key_6:
  26. case Qt::Key_7:
  27. case Qt::Key_8:
  28. case Qt::Key_9:
  29. ret = false;
  30. break;
  31. default:
  32. break;
  33. }
  34. }
  35. else
  36. {
  37. ret = QWidget::eventFilter(obj, e);
  38. }
  39. return ret;
  40. }
  41. bool Widget::event(QEvent* e)
  42. {
  43. if(e->type() == QEvent::KeyPress)
  44. {
  45. qDebug() << "Widget::event";
  46. }
  47. return QWidget::event(e);
  48. }
  49. void Widget::keyPressEvent(QKeyEvent* e)
  50. {
  51. qDebug() << "Widget::keyPressEvent";
  52. QWidget::keyPressEvent(e);
  53. }
  54. Widget::~Widget()
  55. {
  56. }

在使用事件过滤器之前,需要事件过滤的对应组件需要安装事件过滤器;然后重写 eventFilter 函数,eventFilter 返回 true 表示将当前事件过滤;返回 false 表示这个事件会正常传递到目标组件。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/949529
推荐阅读
相关标签
  

闽ICP备14008679号