【已解决】Qt mouseMoveEvent、mouseReleaseEvent失效无法触发

问题背景

我有一个派生自QGraphicsObject的类,这个类其实就是同时继承了QGraphicsItemQObject的类

相当于在QGraphicsItem的基础上增加了事件消息的功能

我派生出来的这个类主要是实现了由多个点组成的多边形

现在想实现一个功能,拖动其中的某个点,改变多边形的形状

目标点已获得

只需要重写mousePressEventmouseMoveEventmouseReleaseEvent实现具体逻辑就可以了

问题

hoverMoveEventmousePressEvent都可以正常触发,但是mouseMoveEventmouseReleaseEvent怎么都触发不了

原因

先看看原本的代码,尤其关注mousePressEvent

cpp 复制代码
void TriangleItem::mousePressEvent(QGraphicsSceneMouseEvent* evt)
{
    _handleIndex = _activeIndex;
    QGraphicsObject::mousePressEvent(evt);
}

void TriangleItem::mouseMoveEvent(QGraphicsSceneMouseEvent* evt)
{
    if (!_isFinished || _handleIndex < 0) {
        QGraphicsObject::mouseMoveEvent(evt);
        return;
    }
    QPointF p = evt->pos();
    // 相关处理逻辑
    // ...
    QGraphicsObject::mouseMoveEvent(evt);
}

void TriangleItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* evt)
{
    _handleIndex = -1;
    QGraphicsObject::mouseReleaseEvent(evt)
}

我在mousePressEvent逻辑实现完后,直接调用了父类的事件处理函数QGraphicsObject::mousePressEvent(evt),把事件交由父类处理,没有accept

在看Qt GraphicsItem mousePressEvent文档中的描述

翻译后大概意思:

对于事件事件,可以重新实现此事件处理程序以接收此项目的鼠标按下事件。鼠标按下事件仅传递给接受按下的鼠标按钮的项目。默认情况下,一个项目接受所有鼠标按钮,但您可以通过调用setAcceptedMouseButtons()来更改这一点。 鼠标按下事件决定哪个项目应该成为鼠标抓取器(请参阅QGraphicsScene::mouseGrabberItem())。如果不重新实现此功能,按下事件将传播到该项目下的任何最上面的项目,并且不会向该项目传递其他鼠标事件。 若重新实现此函数,则默认情况下会接受事件(请参见QEvent::accept()),并且此项就是鼠标抓取器。这允许项目接收未来的移动、释放和双击事件。如果对事件调用QEvent::ignore(),则此项将失去鼠标抓取,并且事件将传播到下面任何最顶层的项。除非收到新的鼠标按下事件,否则不会向该项目传递更多的鼠标事件。 默认实现处理基本的项交互,如选择和移动。如果您想在重新实现此函数时保留基本实现,请在重新实现中调用QGraphicsItem::mousePressEvent()。 对于既不可移动也不可选择的项,事件为QEvent::ignore()

也就是说,如果不accept,那么这个对象就没法接收移动、释放和双击事件

解决

知道了原因就好办

问题出在mousePressEvent,如果确认了需要移动的点,那么就需要accept事件,以允许后续mouseMoveEventmouseReleaseEvent可以被正常触发

cpp 复制代码
void TriangleItem::mousePressEvent(QGraphicsSceneMouseEvent* evt)
{
    if (_activeIndex >= 0) {
        _handleIndex = _activeIndex;
        evt->accept();
    }
    else {
        evt->ignore();
    }
}

void TriangleItem::mouseMoveEvent(QGraphicsSceneMouseEvent* evt)
{
    if (!_isFinished || _handleIndex < 0) {
        QGraphicsObject::mouseMoveEvent(evt);
        return;
    }
    QPointF p = evt->pos();
    // 相关处理逻辑
    QGraphicsObject::mouseMoveEvent(evt);
}

void TriangleItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* evt)
{
    if (_handleIndex >= 0) {
        _handleIndex = -1;
    }
    else {
        evt->ignore();
    }
}

相关内容

QGraphicsItem::mouseReleaseEvent文档也描述了这一点,要想触发mouseReleaseEvent,必须在mousePressEventaccept事件

对于事件事件,可以重新实现此事件处理程序以接收此项的鼠标释放事件。 对事件调用QEvent::ignore()QEvent::accept()无效。 默认实现处理基本的项交互,如选择和移动。如果您想在重新实现此函数时保留基本实现,请在重新实现中调用QGraphicsItem::mouseReleaseEvent()。 请注意,mousePressEvent()决定接收鼠标事件的图形项。有关详细信息,请参阅mousePressEvent()描述。

mouseDoubleClickEventmouseMoveEvent也都是一样的描述

相关推荐
2401_8846022713 小时前
程序人生-Hello’s P2P
c语言·c++
初中就开始混世的大魔王14 小时前
2 Fast DDS Library概述
c++·中间件·信息与通信
娇娇yyyyyy14 小时前
C++基础(6):extern解决重定义问题
c++
Neteen15 小时前
【数据结构-思维导图】第二章:线性表
数据结构·c++·算法
灰色小旋风15 小时前
力扣——第7题(C++)
c++·算法·leetcode
Ralph_Y16 小时前
C++网络:一
开发语言·网络·c++
2345VOR16 小时前
【QT的pyside6开发使用】
开发语言·qt
程序猿编码16 小时前
探秘 SSL/TLS 服务密码套件检测:原理、实现与核心设计(C/C++代码实现)
c语言·网络·c++·ssl·密码套件
Ronin30516 小时前
【Qt常用控件】控件概述和QWidget 核心属性
开发语言·qt·常用控件·qwidget核心属性
故事和你9116 小时前
sdut-程序设计基础Ⅰ-实验二选择结构(1-8)
大数据·开发语言·数据结构·c++·算法·优化·编译原理