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

相关推荐
青草地溪水旁22 分钟前
设计模式(C++)详解—单例模式(2)
c++·单例模式
bkspiderx29 分钟前
C++时区操作全版本指南(含C++03/C++11-17/C++20)
linux·开发语言·c++·c++20·时区
序属秋秋秋1 小时前
《C++进阶之STL》【哈希表】
数据结构·c++·stl·哈希算法·散列表·哈希表·哈希
青草地溪水旁2 小时前
设计模式(C++)详解——建造者模式(1)
c++·设计模式·建造者模式
大可门耳2 小时前
Qt第一课:Qt是什么?相对于其他框架的优劣势是什么
开发语言·qt
axban5 小时前
QT M/V架构开发实战:QFileSystemModel介绍
开发语言·qt·架构
自动驾驶小卡6 小时前
boost::circular_buffer的使用方法简介
c++·boost·circular_buffer
睡不醒的kun8 小时前
leetcode算法刷题的第三十二天
数据结构·c++·算法·leetcode·职场和发展·贪心算法·动态规划
乔宕一10 小时前
stm32 链接脚本没有 .gcc_except_table 段也能支持 C++ 异常
c++·stm32·嵌入式硬件
SuperCandyXu10 小时前
P3205 [HNOI2010] 合唱队-普及+/提高
c++·算法·洛谷