Qt自定义QGraphicsPolygonItem的mousePressEvent不生效问题
问题核心诱因
- 你继承
QGraphicsPolygonItem后,仅在自定义成员变量pol1中存储了箭头的多边形点位,没有调用基类的setPolygon()方法将形状同步给基类。Qt图形视图框架的鼠标命中检测完全依赖图元自身上报的boundingRect()(边界矩形)和shape()(精确形状),QGraphicsPolygonItem默认的这两个返回值都是基于自身内部存储的多边形计算的;未同步形状的情况下,基类会判定该图元是尺寸为0的空对象,鼠标点击时根本不会将该图元纳入命中检测范围,自然不会触发你重写的mousePressEvent。 - 你当前重写的
mousePressEvent没有调用基类的对应实现,就算事件能正常送达,也会打断Qt默认的事件传播链,可能导致后续选中、拖拽等交互逻辑异常。 - 额外隐患:你重写
paint函数时直接绘制自定义成员变量的多边形,没有和基类的形状同步,后续如果修改图元大小、多边形点位,很容易出现绘制内容和命中区域不匹配、渲染残影等问题。
可行解决方案
- 构造函数中完成多边形点位定义后,调用
setPolygon()将形状同步给基类,让框架能正确计算图元的可点击区域。 - 重写的事件处理函数中,执行完自定义逻辑后调用基类的对应事件方法,保证事件传播正常。
- (可选)移除冗余的自定义多边形成员变量,直接使用基类提供的
polygon()/setPolygon()接口管理形状,避免绘制内容和命中区域不一致。如果不需要高度自定义绘制逻辑,甚至可以直接删除重写的paint函数,通过基类的setBrush()接口设置填充色即可。
修改后代码
tranzicija.h
#include <QObject> #include <QGraphicsPolygonItem> #include <QGraphicsSceneMouseEvent> #include <QPainter> class tranzicija:public QObject,public QGraphicsPolygonItem { Q_OBJECT public: tranzicija(); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override; void mousePressEvent(QGraphicsSceneMouseEvent *event) override; private: // 可选:如果不需要额外操作,可以删掉pol1成员,直接用基类接口管理多边形 QPolygonF pol1; void pomjeriproces(); };
tranzicija.cpp
#include "tranzicija.h" #include <QDebug> tranzicija::tranzicija() { pol1 << QPointF(0,45) << QPointF(60,45) << QPointF(60,35) << QPointF(100, 50) << QPointF(60,65) << QPointF(60,55) << QPointF(0,55) << QPointF(0,45); // 核心修复:将多边形同步给基类,用于命中检测和边界计算 setPolygon(pol1); // 如果不需要自定义paint,直接设置画刷即可,无需重写paint // setBrush(Qt::green); } void tranzicija::mousePressEvent(QGraphicsSceneMouseEvent *event) { qDebug() << "The button was pressed!"; // 调用基类实现,保证事件传播正常 QGraphicsPolygonItem::mousePressEvent(event); } void tranzicija::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); QBrush brush(Qt::green); painter->setBrush(brush); painter->setRenderHint(QPainter::Antialiasing); // 推荐直接调用基类的polygon()获取形状,避免和设置的命中区域不一致 painter->drawPolygon(polygon()); }
dialog.cpp(原有逻辑无需修改,可直接生效)
//Poligon start => ready tranzicija *tr = new tranzicija(); tr->setRotation(45); tr->setPos(170,125); tr->setScale(0.8); scene->addItem(tr);
补充说明:如果后续需要给图元添加选中、拖拽、悬浮等交互效果,只需要通过
setFlag()方法开启对应的图元标志即可,例如tr->setFlag(QGraphicsItem::ItemIsSelectable, true);即可开启选中支持。
内容的提问来源于stack exchange,提问作者Don Marquez
相关产品推荐
相关产品推荐

