【已解决】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也都是一样的描述

相关推荐
Cinema KI33 分钟前
吃透C++继承:不止是代码复用,更是面向对象设计的底层思维
c++
Dream it possible!3 小时前
LeetCode 面试经典 150_二叉搜索树_二叉搜索树中第 K 小的元素(86_230_C++_中等)
c++·leetcode·面试
友友马3 小时前
『QT』窗口 (一)
开发语言·数据库·qt
Bona Sun5 小时前
单片机手搓掌上游戏机(十四)—pico运行fc模拟器之电路连接
c语言·c++·单片机·游戏机
oioihoii5 小时前
性能提升11.4%!C++ Vector的reserve()方法让我大吃一惊
开发语言·c++
小狗爱吃黄桃罐头5 小时前
《C++ Primer Plus》模板类 Template 课本实验
c++
码力码力我爱你8 小时前
Harmony OS C++实战
开发语言·c++
Vect__8 小时前
别再只懂 C++98!C++11 这7个核心特性,直接拉开你与普通开发者的差距
c++
想唱rap8 小时前
C++ map和set
linux·运维·服务器·开发语言·c++·算法
小欣加油9 小时前
leetcode 1018 可被5整除的二进制前缀
数据结构·c++·算法·leetcode·职场和发展