[Interest] Unable to receive mouse move events by a QGraphicsItem.

Dmitrii Volosnykh dmitrii.volosnykh at gmail.com
Fri Jan 17 09:30:19 CET 2014


I enabled mouse tracking for QGraphicsView:

[code]
    ui->graphicsView->setMouseTracking(true);
    qDebug() << "mouse tracking:" << ui->graphicsView->hasMouseTracking();
[/code]

but that does not help.


2014/1/17 Dmitrii Volosnykh <dmitrii.volosnykh at gmail.com>

> Hi,
>
> basically, I am trying to implement edition of polyline. I construct it by
> a set of QGraphicsEllipseItem's connected with QGraphicsLineItem's. All of
> them are descendants of PolylineItem inherited from QGraphicsItem.
>
> In order to make vertices moveable I need to intercept mouse move events
> in QGraphicsEllipseItem.
>
> The main.cpp is autogenerated and does not need to be changed for the
> purpose of minimal example. Construction of the scene is done in the
> constructor of MainWindow class:
>
> [code]
> #ifndef MAINWINDOW_H
> #define MAINWINDOW_H
>
> #include <QtWidgets/QMainWindow>
> #include <QtCore/QScopedPointer>
>
> namespace Ui {class MainWindow;}
> QT_FORWARD_DECLARE_CLASS(QGraphicsScene)
>
>
> class MainWindow : public QMainWindow
> {
>     Q_OBJECT
>
> public:
>     explicit MainWindow(QWidget* parent = nullptr);
>     virtual ~MainWindow();
>
> private:
>     const QScopedPointer<QGraphicsScene> m_scene;
>     const QScopedPointer<Ui::MainWindow> ui;
> };
>
> #endif // MAINWINDOW_H
> [/code]
>
> Here's MainWindow.cpp:
>
> [code]
> #include "mainwindow.h"
> #include "polylineitem.h"
> #include "ui_mainwindow.h"
> #include <QtCore/QTimer>
> #include <QtWidgets/QGraphicsScene>
>
>
> MainWindow::MainWindow(QWidget* parent)
>     : QMainWindow(parent)
>     , m_scene(new QGraphicsScene)
>     , ui(new Ui::MainWindow)
> {
>     ui->setupUi(this);
>
>     ui->graphicsView->setScene(m_scene.data());
>
>     auto* const polyline = new PolylineItem;
>     polyline->addPoint(QPointF(10, 10));
>     polyline->addPoint(QPointF(100, 100));
>
>     auto pen = polyline->linePen();
>     pen.setWidthF(4);
>     pen.setCosmetic(true);
>     polyline->setPen(pen);
>
>     m_scene->setSceneRect(QRectF(-50, -50, 200, 200));
>
>     m_scene->addItem(polyline);
> }
>
> MainWindow::~MainWindow()
> {}
> [/code]
>
> The polyline class follows:
>
> [code]
> #ifndef POLYLINEITEM_H
> #define POLYLINEITEM_H
>
> #include <QtGui/QPen>
> #include <QtWidgets/QGraphicsItemGroup>
>
>
> class PolylineItem : public QGraphicsItem
> {
> public:
>     explicit PolylineItem(QGraphicsItem* parent = nullptr);
>
>     void addPoint(const QPointF& point, bool highlighted = false);
>
>     bool isEmpty() const;
>
>     QRectF boundingRect() const override;
>     void paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
> QWidget* widget = nullptr) override;
>
>     void pointMoved(QGraphicsEllipseItem* point);
>
>     void setPen(const QPen& pen);
>
>     void setLinePen(const QPen& pen);
>     QPen linePen() const;
>
>     void setPointPen(const QPen& pen);
>     QPen pointPen() const;
>
> protected:
>     bool sceneEvent(QEvent* event) override;
>     void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
>
> private:
>     QList<QGraphicsEllipseItem*> m_points;
>     QList<QGraphicsLineItem*> m_lines;
>     QPen m_linePen;
>     QPen m_pointPen;
> };
>
> #endif // POLYLINEITEM_H
> [/code]
>
>
> And polylineitem.cpp:
>
> [code]
> #include "polylineitem.h"
> #include <QtWidgets/QGraphicsSceneEvent>
>
> #include <QtCore/QtDebug>
>
>
> namespace
> {
>     const qreal POINT_RADIUS_RATIO = 1.5;
>     const QColor POINT_HIGHLIGHT_COLOR = Qt::green;
>
>
>     class PointItem : public QGraphicsEllipseItem
>     {
>     public:
>         explicit PointItem(PolylineItem* polyline = nullptr);
>
>         void setHighlighted(bool highlighted);
>         bool highlighted() const;
>
>     protected:
>         bool sceneEvent(QEvent* event) override;
>         void hoverEnterEvent(QGraphicsSceneHoverEvent* event) override;
>         void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override;
>         void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
>         void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
>         void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
>
>     private:
>         PolylineItem* const m_polyline;
>         QColor m_color;
>         bool m_moving;
>         QPointF m_prevPos;
>     };
>
>
>     PointItem::PointItem(PolylineItem* const polyline)
>         : QGraphicsEllipseItem(polyline)
>         , m_polyline(polyline)
>     {
>         setAcceptHoverEvents(true);
>     }
>
>     void PointItem::setHighlighted(const bool highlighted)
>     {
>         auto p = pen();
>         if (highlighted) {
>             m_color = p.color();
>             p.setColor(POINT_HIGHLIGHT_COLOR);
>         } else {
>             p.setColor(m_color);
>             m_color = QColor();
>         }
>         setPen(p);
>     }
>
>     bool PointItem::highlighted() const
>     {
>         return m_color.isValid();
>     }
>
>     bool PointItem::sceneEvent(QEvent* const event)
>     {
>         qDebug() << "PointItem::sceneEvent" << event->type();
>
>         return QGraphicsEllipseItem::sceneEvent(event);
>     }
>
>     void PointItem::hoverEnterEvent(QGraphicsSceneHoverEvent* const event)
>     {
>         setHighlighted(true);
>
>         QGraphicsEllipseItem::hoverEnterEvent(event);
>     }
>
>     void PointItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* const event)
>     {
>         setHighlighted(false);
>
>         QGraphicsEllipseItem::hoverLeaveEvent(event);
>     }
>
>     void PointItem::mousePressEvent(QGraphicsSceneMouseEvent* const event)
>     {
>         m_moving = true;
>         m_prevPos = event->scenePos();
>
>         QGraphicsEllipseItem::mousePressEvent(event);
>     }
>
>     void PointItem::mouseMoveEvent(QGraphicsSceneMouseEvent* const event)
>     {
>         qDebug() << "PointItem::mouseMoveEvent";
>
>         QGraphicsEllipseItem::mouseMoveEvent(event);
>     }
>
>     void PointItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* const
> event)
>     {
>         QGraphicsEllipseItem::mouseReleaseEvent(event);
>
>         m_moving = false;
>     }
> }
>
>
> PolylineItem::PolylineItem(QGraphicsItem* const parent)
>     : QGraphicsItem(parent)
> {
>     setFlag(QGraphicsItem::ItemHasNoContents);
> }
>
> void PolylineItem::addPoint(const QPointF& point, const bool highlighted)
> {
>     const qreal r = m_pointPen.widthF() * POINT_RADIUS_RATIO;
>
>     auto* const newPointItem = new PointItem(this);
>     newPointItem->setPos(point);
>     newPointItem->setRect(-r, -r, 2 * r, 2 * r);
>     newPointItem->setPen(m_pointPen);
>     newPointItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);
>     newPointItem->setZValue(zValue() + 1);
>     newPointItem->setHighlighted(highlighted);
>     m_points.append(newPointItem);
>
>     if (m_points.size() > 1) {
>         auto* const prevPointItem = m_points[m_points.size() - 2];
>
>         auto* const lineItem = new QGraphicsLineItem(this);
>         lineItem->setLine(QLineF(prevPointItem->pos(),
> newPointItem->pos()));
>         lineItem->setPen(m_linePen);
>         m_lines.append(lineItem);
>     }
> }
>
> bool PolylineItem::isEmpty() const
> {
>     return m_points.isEmpty();
> }
>
> QRectF PolylineItem::boundingRect() const
> {
>     QRectF result;
>
> //    for (int i = 0; i < m_points.size(); ++i) {
> //        result |=
> m_points[i]->boundingRect().translated(m_points[i]->pos());
> //    }
>
>     return result;
> }
>
> void PolylineItem::paint(QPainter* const painter, const
> QStyleOptionGraphicsItem* const option, QWidget* const widget)
> {
>     Q_UNUSED(painter);
>     Q_UNUSED(option);
>     Q_UNUSED(widget);
> }
>
> void PolylineItem::pointMoved(QGraphicsEllipseItem* const point)
> {
>     const int pointIndex = m_points.indexOf(point);
>     Q_ASSERT(pointIndex >= 0);
>
>     // TODO
> }
>
> void PolylineItem::setPen(const QPen& pen)
> {
>     setLinePen(pen);
>     setPointPen(pen);
> }
>
> void PolylineItem::setLinePen(const QPen& pen)
> {
>     m_linePen = pen;
>
>     foreach (QGraphicsLineItem* const line, m_lines) {
>         line->setPen(pen);
>     }
> }
>
> QPen PolylineItem::linePen() const
> {
>     return m_linePen;
> }
>
> void PolylineItem::setPointPen(const QPen& pen)
> {
>     m_pointPen = pen;
>
>     foreach (QGraphicsEllipseItem* const point, m_points) {
>         point->setPen(pen);
>     }
> }
>
> QPen PolylineItem::pointPen() const
> {
>     return m_pointPen;
> }
>
> bool PolylineItem::sceneEvent(QEvent* const event)
> {
>     qDebug() << "PolylineItem::sceneEvent" << event->type();
>
>     return QGraphicsItem::sceneEvent(event);
> }
>
> void PolylineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* const event)
> {
>     qDebug() << "PolylineItem::mouseMoveEvent";
>
>     QGraphicsItem::mouseMoveEvent(event);
> }
> [/code]
>
>
> When I run application and move mouse over one of the circles at the ends
> of line segment, I get the following debug output log:
>
> PolylineItem::sceneEvent 24
>
> PointItem::sceneEvent 24
>
> PointItem::sceneEvent 24
>
> PointItem::sceneEvent 160
>
> PointItem::sceneEvent 161
>
> PointItem::sceneEvent 161
>
> PointItem::sceneEvent 161
>
> PointItem::sceneEvent 161
>
> PointItem::sceneEvent 161
>
> PointItem::sceneEvent 161
>
> PointItem::sceneEvent 161
>
> PointItem::sceneEvent 162
>
> PolylineItem::sceneEvent 25
>
> PointItem::sceneEvent 25
>
> PointItem::sceneEvent 25
>
>
> So, disregarding any WindowActivate = 24 and WindowDeactivate = 25 events,
> I get only a set of GraphicsSceneHoverEnter = 160, GraphicsSceneHoverMove =
> 161, and GraphicsSceneHoverLeave = 162 events.
>
> Hover move event is not sufficient for me, because the point moving
> behaviour gets broken with rapid mouse motion. That's why need
> mouseMoveEvent() to be called.
>
> Any suggestions on where this event might be blocked? I have re-read the
> "Event Handling and Propagation" chapter of QGraphicsScene manual, but
> still striking with the issue.
>
> Regards,
> Dmitrii.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20140117/47222835/attachment.html>


More information about the Interest mailing list