Qt自定义控件 —— 子控件与父控件的鼠标事件问题

这篇具有很好参考价值的文章主要介绍了Qt自定义控件 —— 子控件与父控件的鼠标事件问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

0、引言:

1、问题描述:

2、解决方案:

3、解决后效果:


0、引言:

Qt自定义控件 —— 颜色选择组合控件https://blog.csdn.net/YMGogre/article/details/128955257一文中我们创建了自定义的组合控件,在该控件中包含了三个子控件 —— QGraphicsViewQLineEditQPushButton。当我们通过 setItemWidget() 方法将自定义控件设置到 QTreeWidgetQTableWidgetQListWidgetitem(QTreeWidegtItemQTableWidgetItemQListWidgetItem) 中时,可能会发现下面这种奇怪的现象(以 QTreeWidget 的 QTreeWidegtItem 为例):

Qt自定义控件 —— 子控件与父控件的鼠标事件问题

1、问题描述:

        可以看到,当 Qt 自带的控件(比如“网格”项第二列的 QCheckBox、“平面单元格数”项第二列的 QSpinBox 等)通过 setItemWidget() 方法设置到 QTreeWidegtItem 中时,我们去点击这些 Qt 自带的控件那么其所在的 QTreeWidegtItem 也会被选中;而对于我们自定义的控件,就有那么些许不同了:

  1. 对于自定义控件中的三个子控件 —— QGraphicsViewQLineEditQPushButton,我们去点击它们时,自定义控件所在的 QTreeWidegtItem 会被选中;
  2. 当我们点击自定义控件区域内、三个子控件区域外的自定义控件区域时,和 Qt 自带的控件一样,自定义控件所在的 QTreeWidegtItem 会被选中;

        由上面两点我们基本就可以判断出问题所在了:

  • setItemWidget() 方法在把控件设置到 QTreeWidegtItem 中的同时也会建立一种绑定关系,这使得我们在点击控件对象(比如上面 GIF 图中这个自定义控件的空白区域)时会自动去选中其所在的 QTreeWidegtItem。这是Qt框架自动完成的事儿,我们无需手动去做。
  • 当自定义控件中存在子控件时,在任意子控件上点击,此时点击响应会响应到子控件上;而自定义控件本身不会产生任何响应。
  • 所以,QTreeWidegtItem、自定义控件、自定义控件的子控件三者的关系应该如下图所示:

    Qt自定义控件 —— 子控件与父控件的鼠标事件问题

2、解决方案:

        我们已经理解了 setItemWidget() 方法已经将自定义控件和 QTreeWidget 项建立了关联了,既然子控件和自定义控件之间没有鼠标事件关联,那我们可以重写自定义控件的 mousePressEvent() 方法或者 eventFilter() 方法来达到我们的目的,这里笔者选择重写事件过滤器(eventFilter)方法:

  1. 在自定义控件的 .h 文件内包含相关头文件并声明重写事件过滤器方法:
    #include <QEvent>
    #include <QMouseEvent>
    #include <QPushButton>
    
    ...
    
    protected:
        bool eventFilter(QObject *watchedm, QEvent *event) override;    //重写事件过滤器方法
  2. .cpp 文件内自定义控件的构造函数中为需要的子控件安装事件过滤器:
    ...
    
    /*QGraphicsView的鼠标事件会传递给它所显示的QGraphicsScene,然后再传递给场景中的QGraphicsItem。
    由于我们并没有设置任何的QGraphicsScene场景,所以我们设置该控件属性:传递给父对象做鼠标事件处理*/
    ui->ColorDisplay->setAttribute(Qt::WA_TransparentForMouseEvents);
    
    /*****************************************
     * 为自定义控件的子控件安装该自定义控件的事件过滤器
     ****************************************/
    ui->ColorLineEdit->installEventFilter(this);
    ui->btn_SelectColor->installEventFilter(this);
  3. 在事件过滤器方法中检测鼠标点击事件,通过代码选中自定义控件,随后传递事件给子控件让其正常响应点击:
    /**
     * @brief 重写事件过滤器方法
     * @attention 这里简要说下为什么要重写该方法,这是因为当我们的自定义控件中有其他子控件时,
     * 点击子控件的点击响应是相应到子控件上的,而通常我们希望所有子控件的父对象(也就是自定义控
     * 件本身)也会在点击这些子控件时有响应
     * @param QMouseEvent *event ———— 事件对象
     */
    bool MyPalette::eventFilter(QObject *watched, QEvent *event)
    {
      //拦截子控件的鼠标按下或释放事件
      if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease)
      {
        //QEvent类型转换为QMouseEvent类型
        QMouseEvent *mouseevent = static_cast<QMouseEvent *>(event);
        this->QWidget::mousePressEvent(mouseevent);    //调用基类的mousePressEvent方法
        //如果事件的被监视对象是QPushButton
        if(qobject_cast<QPushButton *>(watched))
          this->setFocus();     //设置自定义控件本身获得焦点
    
        return false;     //传递事件给子控件,让其正常响应点击
        //return true;    //事件处理完毕(不传递事件给子控件,只响应自定义控件本身被选中)
      }
      //其他类型的事件交由基类处理
      return QWidget::eventFilter(watched, event);
    }

        由上面三个步骤可以看到,我们设置了 QGraphicsView 由其父对象(自定义控件对象)做鼠标事件处理;而 QLineEdit 和 QPushButton 则是安装了事件过滤器并拦截这两个子控件的鼠标按下或释放事件。

        这是因为 QGraphicsView 只是作为显示颜色的控件,它无需与用户交互,所以让它的父对象来做事件处理就行了;而  QLineEdit 和 QPushButton 自己也需要响应鼠标事件(比如点击  QLineEdit 文本框进入编辑模式以及点击 QPushButton 按钮打开窗口),所以需要安装事件过滤器对自定义控件做处理并在处理完成后将事件传递给子控件让其正常响应。

        此外,在事件过滤器方法中可能会产生疑惑的代码:

//如果事件的被监视对象是QPushButton
if(qobject_cast<QPushButton *>(watched))
  this->setFocus();     //设置自定义控件本身获得焦点
  • 为什么只有被监视对象是 QPushButton 时才设置自定义控件获得焦点?QLineEdit 和 QPushButton 不都安装了事件过滤器吗?

答:因为 QLineEdit 的操作是点击文本框,进入编辑模式。而那个时候文本框是获得焦点的对象,如果让自定义控件获得了焦点点击文本框就不会进入编辑模式了。

  • 为什么需要这两句代码呢?

答:其实我也不太懂,即便使用 QWidget::mousePressEvent(mouseevent); 调用了基类的mousePressEvent方法仍然无法在点击按钮时选中自定义控件本身,所以还是用了这两句代码让自定义控件获得焦点。(欢迎大佬评论区指点迷津🙁)

3、解决后效果:

Qt自定义控件 —— 子控件与父控件的鼠标事件问题文章来源地址https://www.toymoban.com/news/detail-492476.html

到了这里,关于Qt自定义控件 —— 子控件与父控件的鼠标事件问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Qt图形视图框架】自定义QGraphicsItem和QGraphicsView,实现鼠标(移动、缩放)及键盘事件、右键事件

    说明 在使用Qt的图形视图框架实现功能时,一般会在其基础上进行自定义功能实现。 如:滚轮对场景的缩放,鼠标拖动场景中的项,以及可以在场景中进行右键操作等。 示例 myitem 为自定义QGraphicsItem,实现了边框、重绘事件、鼠标悬停、按键、右键菜单等功能。 myitem.h myi

    2024年02月04日
    浏览(50)
  • QT 触控事件和鼠标事件的分离(问题已解决)

    问题:QT图形视图框架,QGraphicsScene中默认接收触控事件,会将第一个点当作鼠标事件处理。 在开发者开发的时候,可能会有这样的需求,希望自己的触控事件和鼠标事件能够分割开来。 找到的解决方法: 方案一: 问题没有解决,修改这两个参数,也无法让QT的触控单击事件

    2024年02月16日
    浏览(36)
  • QT笔记——QSlider滑动条滚轮事件和点击鼠标位置事件问题

    需求:我们需要对一个滑动条 滚轮事件 和 点击到滑动条的位置 实时显示 问题:其中在做的时候遇到了很多的问题,一开始感觉很简单,现在将这些问题记录下来 ui图: 问题1:处理QSlider 滚轮事件的时候 这里有很大的问题,但是不知道原因,为什么会出现这样的原因,网上

    2024年02月01日
    浏览(45)
  • Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化

    Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化 1、main.cpp 2、widget.h 3、widget.cpp 4、效果展示 5、完成

    2024年02月16日
    浏览(70)
  • VBA combox/listbox 控件响应鼠标滚轮事件

    在vba中,我们在用户窗体中如果添加有combox控件,或者是listbox控件。正常情况下,combox 和 listbox 是不响应鼠标滚轮事件的,且默认的VBA控件中,也没有提供响应鼠标滚轮事件的方法和入口。如此以来,我们在combox/listbox 中操作选择目标选项,就只能使用滚动条来操作,严重

    2024年04月09日
    浏览(65)
  • vue子元素点击事件与父元素点击事件冲突 子元素点击事件不触发

    在vue项目中,子元素有点击事件,父元素也有点击事件,当点击子元素时往往触发的是父元素的点击事件,产生冲突,怎样解决这个问题呢? 解决方法:使用vue中的事件修饰符 vue为 v-on 提供了 .stop、.prevent、.self、.once等事件修饰符,当遇到子元素与父元素的事件冲突,就要

    2024年02月14日
    浏览(38)
  • Qt - Qt5事件处理(鼠标事件)

    鼠标事件 ​ 鼠标事件包括鼠标的移动,鼠标键按下,松开,单击,双击等 使用鼠标事件时,加入对应头文件 常见的鼠标事件如下: QMouseEvent类包含了用于描述鼠标事件的参数。 当在一个窗口里按住鼠标按键、或移动、或释放就会产生鼠标事件QMouseEvent。 鼠标移动事件只会

    2023年04月09日
    浏览(42)
  • Qt 事件 < 二 >鼠标键盘事件

    Qt 是一个流行的 C++ 框架,用于构建跨平台的图形用户界面应用程序。在 Qt 中,处理键盘事件和鼠标事件是常见的任务,因为用户输入在交互式应用程序中至关重要。下面是关于 Qt 键盘事件和鼠标事件的学习总结: 键盘事件 (QKeyEvent)使用入门: 事件处理函数: 键盘事件通过

    2024年01月18日
    浏览(42)
  • Qt鼠标拖动控件交换布局位置

    方法很简单,交换鼠标起点控件指针和鼠标落点控件指针的值,然后重新布局 Qt鼠标拖动控件交换布局位置 源文件 头文件 下面是只交换控件显示的内容: 添加鼠标贴图,跟随鼠标移动: 一种实现:重写void paintEvent(QPaintEvent *event);方法 另一种实现:

    2024年02月11日
    浏览(38)
  • qt 怎么检测鼠标在不在某个控件上

    方式一:推荐,感觉这种事件过滤器的方法捕捉比较敏感 记得安装事件过滤器 上面的函数还可以有一层,选择对应的你要哪个控件安装这个事件过滤器 比如: 方式二:重写鼠标事件 如果控件有父亲,记得也要设置鼠标追踪  上面两种方法可以动态的监听鼠标是不是在某个

    2024年02月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包