qt对于一个QWidget的所有事件

65 篇文章 25 订阅

可以看看我其它博客:

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

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个权限层级 (这几个层次的控制权是逐层增大的):

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

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

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) 事件函数里拿到的) 是一个功能的东西吗???我测了一下,效果一样的。如果要实现鼠标移动到子控件上,能够做出响应,那么就去子控件的事件函数里捕获吧。从上面的源码可以看出,不是同一个事件。

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

  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一定不会把事件继续派发给父对象(父控件)。

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事件:

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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值