• qt对于一个QWidget的所有事件


    可以看看我其它博客:

    qt事件循环原理(知根知底) qt源码解析1--事件循环原理(重写事件函数,事件过滤器等)

    qt实现自定义菜单_我是标同学的博客-CSDN博客_qt如何做菜单

    qt QMainWindow窗口鼠标移动事件触发方式_我是标同学的博客-CSDN博客


    打开qwidget.h就能看到了所有的事件

    直接获取操作系统派发的所有事件(最全):

    (虽然Qt事件对于系统的消息做了一些封装,但在实际过程中Qt封装的消息不满足我们,因此我们需要windos消息机制,在判断windows消息时,便要重写nativeEvent事件: Qt重写nativeEvent无响应问题的说明_SUST狗子的博客-CSDN博客_qt nativeevent

    virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result);

    qt封装的所有事件的接口:

    (所有qt封装的事件都会在这里能够获取到,进行 switch 判断即可)

    bool event(QEvent *event) Q_DECL_OVERRIDE;

    qt的源码实现是如下的(一个巨大的 switch 来判断 QEvent 的 type,并且分发给不同的事件处理函数):Qt Event(Qt事件)_HIIWAR_ZB的博客-CSDN博客 这个博客讲得很不错。

    关于返回值的作用,一定要看我这个博客:https://biao2488890051.blog.csdn.net/article/details/127801104?spm=1001.2014.3001.5502

    (返回值true且事件是accept状态,则qt则处理下一个事件了,false:表明这个事件没有处理完,分发器会把该事件给该对象的父对象继续处理),事件默认是accept状态的,QWidget的事件处理函数默认是ignore()的。

    1. bool QWidget::event(QEvent *event) {
    2.         switch (e->type()) {
    3.         case QEvent::KeyPress:
    4.                  keyPressEvent((QKeyEvent *)event);
    5.                 if (!((QKeyEvent *)event)->isAccepted())
    6.                         return false;
    7.                 break;
    8.         case QEvent::KeyRelease:
    9.                 keyReleaseEvent((QKeyEvent *)event);
    10.                 if (!((QKeyEvent *)event)->isAccepted())
    11.                         return false;
    12.                 break;
    13.                 // more...
    14.         }
    15.         return true;
    16. }

    事件处理的5个权限层级 (这几个层次的控制权是逐层增大的):

    1. 重定义事件处理函数(我们一般常用的做法,简单可靠)
    2. 重定义 event()函数
    3. 为单个组件安装事件过滤器
    4. 为 QApplication 安装事件过滤器
    5. 重定义 QCoreApplication 的 notify()函数

    我们重写的使用方式如下:

    1. this->setAttribute(Qt::WA_HOVER, true);
    2. bool Widget::event(QEvent * e)
    3. {
    4. switch(e->type())
    5. {
    6. case QEvent::HoverEnter:
    7. hoverEnter(static_cast(e));
    8. return true;
    9. break;
    10. case QEvent::HoverLeave:
    11. hoverLeave(static_cast(e));
    12. return true;
    13. break;
    14. case QEvent::HoverMove:
    15. hoverMove(static_cast(e));
    16. return true;
    17. break;
    18. default:
    19. break;
    20. }
    21. return QWidget::event(e);
    22. }

    接下来的是qt这些封装事件的具体可以直接用的函数:其实上面的event函数正是调用了下面的函数,才实现的下面这些事件函数的触发的。

    鼠标事件为

    下面这一段是qml才有的,c++ qt QEvent的枚举类型中根本没有这几个类型

    {mouseover和mouseout:当鼠标移入移出元素或子元素都会触发事件。(支持冒泡) mouseenter和mouseleave:当鼠标移入移出元素才会触发事件(子元素不触发)。(不支持冒泡) hover的效果等同于mouseenter,mouseleave。 mouse hover悬浮和mouse enter进入的区别在于:hover事件会让控件发生重绘,而enter不会。所以houver事件一般用于鼠标悬浮在一个控件上,控件此时改变样式,此时控件样式能自动及时的更新显示。}

    c++ qt QEvent 中只有 QEvent::HoverLeave(自己重写event()函数来捕获使用)、QEvent::Leave(有预定义的处理虚函数可用的)。没有所谓的mouseout、mouseleave事件,

    来看看源码:

    bool QWidget::event(QEvent *event)的源码实现如下:
    1. //源码
    2. bool QWidget::event(QEvent *event)
    3. case QEvent::FocusOut:
    4. focusOutEvent((QFocusEvent*)event);
    5. break;
    6. case QEvent::Enter:
    7. #ifndef QT_NO_STATUSTIP
    8. if (d->statusTip.size()) {
    9. QStatusTipEvent tip(d->statusTip);
    10. QApplication::sendEvent(const_cast(this), &tip);
    11. }
    12. #endif
    13. enterEvent(event);
    14. break;
    15. case QEvent::Leave:
    16. #ifndef QT_NO_STATUSTIP
    17. if (d->statusTip.size()) {
    18. QString empty;
    19. QStatusTipEvent tip(empty);
    20. QApplication::sendEvent(const_cast(this), &tip);
    21. }
    22. #endif
    23. leaveEvent(event);
    24. break;
    25. case QEvent::HoverEnter:
    26. case QEvent::HoverLeave:
    27. update();
    28. break;

    下面的是qt c++的定义好的事件函数:(我们只需要关注enterEvent,leaveEvent即可)

    这里我有个疑问:直接的leaveEvent函数,和 event->type() == QEvent::HoverLeave(event(QEvent *event) 事件函数里拿到的) 是一个功能的东西吗???我测了一下,效果一样的。如果要实现鼠标移动到子控件上,能够做出响应,那么就去子控件的事件函数里捕获吧。从上面的源码可以看出,不是同一个事件。

    再来看看这两个事件产生的源码:

    1. 先产生一个 Leave 事件,用的是QApplication::sendEvent(w, &leaveEvent); 函数,说明这个事件会在这里被立即派发了。
    2. 可以看出如果开了widget开了 Qt::WA_Hover 属性,那么顺便再产生一个 HoverLeave 事件,用的是notify_helper(w, &he);函数,说明这个事件不会派发给对象w的父对象,关于原理看我这个博客 https://biao2488890051.blog.csdn.net/article/details/127801104?spm=1001.2014.3001.5502

     因此也就解释了,在widget开了 Qt::WA_Hover 属性前提下,  QEvent::HoverLeave,和 QEvent::Leave 产生条件是相同的,因此触发效果是一样的。其中QEvent::HoverLeave一定不会把事件继续派发给父对象(父控件)。

    1. void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
    2. QEvent leaveEvent(QEvent::Leave);
    3. for (int i = 0; i < leaveList.size(); ++i) {
    4. w = leaveList.at(i);
    5. if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
    6. QApplication::sendEvent(w, &leaveEvent);
    7. if (w->testAttribute(Qt::WA_Hover) &&
    8. (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
    9. Q_ASSERT(instance());
    10. QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos),
    11. QApplication::keyboardModifiers());
    12. qApp->d_func()->notify_helper(w, &he);
    13. }
    14. }
    15. }

    可能得先写一行代码

    widget->setMouseTracking(true);
    1. virtual void mousePressEvent(QMouseEvent *event);
    2. virtual void mouseReleaseEvent(QMouseEvent *event);
    3. virtual void mouseDoubleClickEvent(QMouseEvent *event);
    4. virtual void mouseMoveEvent(QMouseEvent *event);
    5. virtual void wheelEvent(QWheelEvent *event);
    6. //下面这几个也算鼠标事件的,因为鼠标进入,离开,会触发
    7. virtual void focusInEvent(QFocusEvent *event);
    8. virtual void focusOutEvent(QFocusEvent *event);
    9. virtual void enterEvent(QEvent *event);
    10. virtual void leaveEvent(QEvent *event);
    11. virtual void dragEnterEvent(QDragEnterEvent *event);
    12. virtual void dragMoveEvent(QDragMoveEvent *event);
    13. virtual void dragLeaveEvent(QDragLeaveEvent *event);
    14. virtual void dropEvent(QDropEvent *event);

    键盘事件:

    1. virtual void keyPressEvent(QKeyEvent *event);
    2. virtual void keyReleaseEvent(QKeyEvent *event);

    输入法事件:(比如获取到正在输入的中文)

    virtual void inputMethodEvent(QInputMethodEvent *);

    手写板事件:(一般是平板电脑使用)

    1. //平板电脑的触摸屏等会产生的事件(里面会细分为TabletPress、TabletRelease、TabletMove动作)
    2. virtual void tabletEvent(QTabletEvent *event);

    窗体事件:

    1. virtual void paintEvent(QPaintEvent *event);
    2. virtual void moveEvent(QMoveEvent *event);
    3. virtual void resizeEvent(QResizeEvent *event);
    4. virtual void closeEvent(QCloseEvent *event);
    5. virtual void showEvent(QShowEvent *event);
    6. virtual void hideEvent(QHideEvent *event);

    窗体内发生改变的事件:

    (窗口中比如字体改变,风格改变,布局方向改变等都会触发 Qt事件:changeEvent(改变事件)_友善啊,朋友的博客-CSDN博客_changeevent

    virtual void changeEvent(QEvent *);

    产生菜单事件:

    virtual void contextMenuEvent(QContextMenuEvent *event);

    拖拽物体事件:

    1. virtual void dragEnterEvent(QDragEnterEvent *event);
    2. virtual void dragMoveEvent(QDragMoveEvent *event);
    3. virtual void dragLeaveEvent(QDragLeaveEvent *event);
    4. virtual void dropEvent(QDropEvent *event);

    动作action事件:

    (action的改变,添加,移除都会触发这个事件 https://doc.qt.io/qt-5/qactionevent.html

    virtual void actionEvent(QActionEvent *event);

    另一个得到事件的方法:

    安装事件过滤器(这个可以给父对象安装一个过滤器,实现子对象去处理父对象的所有事件。因为事件传递只能是子对象(中产生的事件)->父对象的,安装了这个过滤器后,就实现了子对象也能得到父对象中产生的事件了。此外,互不相关的两个对象(但是都得继承自QObject)也能互相安装的喔。

     qt事件循环原理(知根知底) qt源码解析1--事件循环原理(重写事件函数,事件过滤器等)

     qt事件的触发原理与事件传递顺序_我是标同学的博客-CSDN博客_qt触发事件

    Qt 事件过滤器(秒懂)_Mr.codeee的博客-CSDN博客_qt 事件过滤器

    1. void QObject::installEventFilter(QObject *filterObj)
    2. bool eventFilter(QObject *obj, QEvent *event);

  • 相关阅读:
    AutoHotkey点击命令,鼠标移动到固定坐标单击左键或者双击
    二叉树概述
    文本框内容自动投影,浅谈C#中事件的写法与应用
    Linux 中的权限
    设计模式之策略模式
    点餐小程序实战教程07-点餐功能开发
    C++常用格式化输出转换
    虚拟现实技术教学应用影响因素研究综述
    Ansys Speos | 如何利用Speos联合optiSLang进行光导优化设计
    Redis03:Redis基础知识以及数据类型
  • 原文地址:https://blog.csdn.net/kangkanglhb88008/article/details/127783653