赞
踩
可以看看我其它博客:
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封装的事件都会在这里能够获取到,进行 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()的。
- bool QWidget::event(QEvent *event) {
-
- switch (e->type()) {
-
- case QEvent::KeyPress:
-
- keyPressEvent((QKeyEvent *)event);
-
- if (!((QKeyEvent *)event)->isAccepted())
-
- return false;
-
- break;
-
- case QEvent::KeyRelease:
-
- keyReleaseEvent((QKeyEvent *)event);
-
- if (!((QKeyEvent *)event)->isAccepted())
-
- return false;
-
- break;
-
- // more...
-
- }
-
- return true;
-
- }
事件处理的5个权限层级 (这几个层次的控制权是逐层增大的):
我们重写的使用方式如下:
- this->setAttribute(Qt::WA_HOVER, true);
-
- bool Widget::event(QEvent * e)
- {
- switch(e->type())
- {
- case QEvent::HoverEnter:
- hoverEnter(static_cast<QHoverEvent*>(e));
- return true;
- break;
- case QEvent::HoverLeave:
- hoverLeave(static_cast<QHoverEvent*>(e));
- return true;
- break;
- case QEvent::HoverMove:
- hoverMove(static_cast<QHoverEvent*>(e));
- return true;
- break;
- default:
- break;
- }
- return QWidget::event(e);
- }
接下来的是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)的源码实现如下:
- //源码
- bool QWidget::event(QEvent *event)
-
- case QEvent::FocusOut:
- focusOutEvent((QFocusEvent*)event);
- break;
-
- case QEvent::Enter:
- #ifndef QT_NO_STATUSTIP
- if (d->statusTip.size()) {
- QStatusTipEvent tip(d->statusTip);
- QApplication::sendEvent(const_cast<QWidget *>(this), &tip);
- }
- #endif
- enterEvent(event);
- break;
-
- case QEvent::Leave:
- #ifndef QT_NO_STATUSTIP
- if (d->statusTip.size()) {
- QString empty;
- QStatusTipEvent tip(empty);
- QApplication::sendEvent(const_cast<QWidget *>(this), &tip);
- }
- #endif
- leaveEvent(event);
- break;
-
- case QEvent::HoverEnter:
- case QEvent::HoverLeave:
- update();
- break;
下面的是qt c++的定义好的事件函数:(我们只需要关注enterEvent,leaveEvent即可)
这里我有个疑问:直接的leaveEvent函数,和 event->type() == QEvent::HoverLeave(event(QEvent *event) 事件函数里拿到的) 是一个功能的东西吗???我测了一下,效果一样的。如果要实现鼠标移动到子控件上,能够做出响应,那么就去子控件的事件函数里捕获吧。从上面的源码可以看出,不是同一个事件。
再来看看这两个事件产生的源码:
因此也就解释了,在widget开了 Qt::WA_Hover 属性前提下, QEvent::HoverLeave,和 QEvent::Leave 产生条件是相同的,因此触发效果是一样的。其中QEvent::HoverLeave一定不会把事件继续派发给父对象(父控件)。
- void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
-
- QEvent leaveEvent(QEvent::Leave);
- for (int i = 0; i < leaveList.size(); ++i) {
- w = leaveList.at(i);
- if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
- QApplication::sendEvent(w, &leaveEvent);
- if (w->testAttribute(Qt::WA_Hover) &&
- (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
- Q_ASSERT(instance());
- QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos),
- QApplication::keyboardModifiers());
- qApp->d_func()->notify_helper(w, &he);
- }
- }
- }
可能得先写一行代码
widget->setMouseTracking(true);
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseReleaseEvent(QMouseEvent *event);
- virtual void mouseDoubleClickEvent(QMouseEvent *event);
- virtual void mouseMoveEvent(QMouseEvent *event);
-
- virtual void wheelEvent(QWheelEvent *event);
-
- //下面这几个也算鼠标事件的,因为鼠标进入,离开,会触发
- virtual void focusInEvent(QFocusEvent *event);
- virtual void focusOutEvent(QFocusEvent *event);
- virtual void enterEvent(QEvent *event);
- virtual void leaveEvent(QEvent *event);
-
- virtual void dragEnterEvent(QDragEnterEvent *event);
- virtual void dragMoveEvent(QDragMoveEvent *event);
- virtual void dragLeaveEvent(QDragLeaveEvent *event);
- virtual void dropEvent(QDropEvent *event);
- virtual void keyPressEvent(QKeyEvent *event);
- virtual void keyReleaseEvent(QKeyEvent *event);
virtual void inputMethodEvent(QInputMethodEvent *);
- //平板电脑的触摸屏等会产生的事件(里面会细分为TabletPress、TabletRelease、TabletMove动作)
- virtual void tabletEvent(QTabletEvent *event);
- virtual void paintEvent(QPaintEvent *event);
- virtual void moveEvent(QMoveEvent *event);
- virtual void resizeEvent(QResizeEvent *event);
- virtual void closeEvent(QCloseEvent *event);
-
- virtual void showEvent(QShowEvent *event);
- virtual void hideEvent(QHideEvent *event);
(窗口中比如字体改变,风格改变,布局方向改变等都会触发 Qt事件:changeEvent(改变事件)_友善啊,朋友的博客-CSDN博客_changeevent)
virtual void changeEvent(QEvent *);
virtual void contextMenuEvent(QContextMenuEvent *event);
- virtual void dragEnterEvent(QDragEnterEvent *event);
- virtual void dragMoveEvent(QDragMoveEvent *event);
- virtual void dragLeaveEvent(QDragLeaveEvent *event);
- virtual void dropEvent(QDropEvent *event);
(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 事件过滤器
- void QObject::installEventFilter(QObject *filterObj)
- bool eventFilter(QObject *obj, QEvent *event);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。