setCursor Confusion
-
I have a class derrived from
QGraphicsView
.Here I use setCursor like this:
void DungeonView::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) { setCursor(Qt::CrossCursor); } else { QGraphicsView::mousePressEvent(event); } } void DungeonView::mouseReleaseEvent(QMouseEvent *event) { if (cursor() == Qt::CrossCursor) { setCursor(Qt::ArrowCursor); } else { QGraphicsView::mouseReleaseEvent(event); } }
This view contains a widget derrived from
QGraphicsWidget
.Here I do this:
void Room::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::MouseButton::LeftButton) { setCursor(Qt::ClosedHandCursor); } } void Room::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton) { setCursor(Qt::OpenHandCursor); } }
My assumption Is what I expect what will happen:
If i press release the right button
DungeonView
handles the changes of the Cursor.
If i press release the left buttonDungeonView
forwards the events to room and it
handles the changes of the Cursor.However if I pressed the left Button I alway see the Cursor of the left button. Event if I use right button again I always see the Cursor from the left button.
It looks like
Room
never gives the events toDungeonView
back. Why is that so ? -
Hi,
Why don't you call the base class implementation in your Room subclass ?
-
Hi
In room, try calling
https://doc.qt.io/qt-5/qevent.html#ignore -
I tryed this but still the hand cursors from
Room
stay.void Room::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::MouseButton::LeftButton) { setCursor(Qt::ClosedHandCursor); } else { event->ignore(); QGraphicsWidget::mousePressEvent(event); } } void Room::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton) { setCursor(Qt::OpenHandCursor); } else { event->ignore(); QGraphicsWidget::mouseReleaseEvent(event); } }
how is the correct way use
ignore
or forward to the parent? -
Don't call both.
-
I also tryed to call only one but same behaviour.
-
Can you provide a minimal compilable example that shows that behaviour ?
-
@sandro4912 said in setCursor Confusion:
QGraphicsWidget::mouseReleaseEvent(event);
Sorry for the delay. Here is the minimal example. If you click in the rectangle with right or left it should toggle hand cursor or cross. However if hand cursor was active the cross gets never enabled again.
#ifndef ROOM_H #define ROOM_H #include <QGraphicsWidget> class Room : public QGraphicsWidget { Q_OBJECT public: explicit Room(QGraphicsItem *parent = nullptr); QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; protected: void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; }; #endif // ROOM_H
#include "room.h" #include <QGraphicsSceneMouseEvent> #include <QPainter> #include <QCursor> Room::Room(QGraphicsItem *parent) :QGraphicsWidget{ parent } { resize(boundingRect().size()); } QRectF Room::boundingRect() const { return QRectF{QPointF{0, 0}, QPointF{100, 100}}; } void Room::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->drawRect(QRectF{ QPointF{0, 0}, QPointF{100, 100}}); } void Room::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::MouseButton::LeftButton) { setCursor(Qt::ClosedHandCursor); } else { event->ignore(); //QGraphicsWidget::mousePressEvent(event); } } void Room::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton) { setCursor(Qt::OpenHandCursor); } else { event->ignore(); //QGraphicsWidget::mouseReleaseEvent(event); } }
#ifndef DUNGEONVIEW_H #define DUNGEONVIEW_H #include <QGraphicsView> class DungeonView : public QGraphicsView { Q_OBJECT public: protected: void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; }; #endif // DUNGEONVIEW_H
#include "dungeonview.h" #include <QMouseEvent> void DungeonView::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) { setCursor(Qt::CrossCursor); } else { QGraphicsView::mousePressEvent(event); } } void DungeonView::mouseReleaseEvent(QMouseEvent *event) { if (cursor() == Qt::CrossCursor) { setCursor(Qt::ArrowCursor); } else { QGraphicsView::mouseReleaseEvent(event); } }
#ifndef DUNGEON_H #define DUNGEON_H #include <QWidget> class QGraphicsScene; class DungeonView; class Room; class Dungeon : public QWidget { Q_OBJECT public: explicit Dungeon(QWidget *parent = nullptr); private: QGraphicsScene *mGraphicsScene; DungeonView *mDungeonView; Room *mRoom; }; #endif // DUNGEON_H
#include "dungeon.h" #include "room.h" #include "dungeonview.h" #include <QVBoxLayout> Dungeon::Dungeon(QWidget *parent) :QWidget{ parent }, mGraphicsScene{ new QGraphicsScene }, mDungeonView{ new DungeonView }, mRoom{ new Room } { mRoom->setPos(QPoint{200, 200}); mRoom->show(); mGraphicsScene->addItem(mRoom); mDungeonView->setScene(mGraphicsScene); auto layout = new QVBoxLayout; layout->addWidget(mDungeonView); setLayout(layout); }
#include "dungeon.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication app{ argc, argv }; Dungeon dungeon; dungeon.show(); return QApplication::exec(); }
-
From the QGraphicsItem::mousePressEvent documentation:
The event is QEvent::ignore()d for items that are neither movable nor selectable.
You have to make your item at least selectable for mouseReleaseEvent to be called.
-
@SGaist said in setCursor Confusion:
selectable
I tryed
setFlag(QGraphicsWidget::ItemIsSelectable);
in the constructor ofRoom
but it still does not work. -
What version of Qt are you using ?
On what OS ?Works fine on macOS High Sierra with Qt 5.13.1.
-
@SGaist
I observed a strange behaviour on Windows.- Right button press on DungeonView shows CrossCursor
- Right button release on DungeonView shows ArrowCursor
- Left button press on DungeonView shows ClosedHandCursor
- Left button release on DungeonView shows OpenHandCursor
- Right button press on DungeonView shows ArrowCursor (expect CrossCursor as step1)
-
I use KDE Neon 5.17 with Qt 5.13.2.
My behaviour is like this:
Right button press on DungeonView shows CrossCursor
Right button release on DungeonView shows ArrowCursor
Left button press on DungeonView shows ClosedHandCursor
Left button release on DungeonView shows OpenHandCursor
Now I only can trigger the HandCursors. The CrossCursor never shows up again.I also testet it on Windows 10 which results in the same behaviour.