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

Dmitrii Volosnykh dmitrii.volosnykh at gmail.com
Fri Jan 17 09:46:29 CET 2014


The problem solved by setting flag QGraphicsItem::ItemIsMovable on each
PointItem created. No need for explicit enabling of mouse tracking for
QGraphicsView.


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

> 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/55e3ed06/attachment.html>


More information about the Interest mailing list