[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