当前位置:   article > 正文

qt对于一个QWidget的所有事件

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<QHoverEvent*>(e));
  8. return true;
  9. break;
  10. case QEvent::HoverLeave:
  11. hoverLeave(static_cast<QHoverEvent*>(e));
  12. return true;
  13. break;
  14. case QEvent::HoverMove:
  15. hoverMove(static_cast<QHoverEvent*>(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<QWidget *>(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<QWidget *>(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);

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

闽ICP备14008679号