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

相关推荐
D_evil__14 小时前
【Effective Modern C++】第二章 auto:6. 当auto推导的类型不符合要求时,使用显式类型初始化习惯用法
c++
钱彬 (Qian Bin)14 小时前
项目实践17—全球证件智能识别系统(开发基于LabelMe标注的可视化审核接口)
qt·fastapi·全球证件识别
哈哈不让取名字14 小时前
基于C++的爬虫框架
开发语言·c++·算法
剑锋所指,所向披靡!17 小时前
C++之类模版
java·jvm·c++
C+-C资深大佬18 小时前
C++风格的命名转换
开发语言·c++
No0d1es18 小时前
2025年粤港澳青少年信息学创新大赛 C++小学组复赛真题
开发语言·c++
点云SLAM18 小时前
C++内存泄漏检测之手动记录法(Manual Memory Tracking)
开发语言·c++·策略模式·内存泄漏检测·c++实战·new / delete
好评12418 小时前
【C++】二叉搜索树(BST):从原理到实现
数据结构·c++·二叉树·二叉搜索树
zylyehuo18 小时前
error: no matching function for call to ‘ros::NodeHandle::param(const char [11], std::string&, const char [34])’
c++·ros1
星火开发设计19 小时前
C++ 函数定义与调用:程序模块化的第一步
java·开发语言·c++·学习·函数·知识