[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