QGraphicsItem to react on CTRL left click
-
@JanLaloux
Ok, Im on mobile so cant check the code.
Have a look at the 40000 sample (in chip.h)
It has a clickable item. -
I noticed in Chip that the event passed is of type
QGraphicsSceneMouseEvent *
instead ofQMouseEvent *
. Changed it and now it works, even aspublic
. Thanks for the support!@JanLaloux
Good spotted! :) -
On a side note: when overriding virtual methods use the override specifier. This way you'll get an instant error message at compile time if you make a typo or mismatch arguments like in this case.
-
I have modified my example. The mouse click works but I experience something strange. After something was clicked whatever click anywhere on the scene triggers the same mouse click method of the first clicked object! Any ideas on this?
#include <string>; #include <QtWidgets/QApplication> #include <QtWidgets/QMessageBox> #include <QtWidgets/QMainWindow> #include <QtWidgets/QGraphicsScene> #include <QtWidgets/QGraphicsView> #include <QtWidgets/QGridLayout> #include <QtWidgets/QGraphicsEllipseItem> using namespace std; class Circle : public QGraphicsEllipseItem { public: Circle::Circle(int Id, const qreal ax, const qreal ay, const qreal wx, const qreal wy, QGraphicsScene *scene) : QGraphicsEllipseItem(ax, ay, wx, wy), Id(Id) { setPen( QPen(QBrush(Qt::black), 1, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin) ); setBrush( QBrush(Qt::gray) ); setRect(ax, ay, wx, wy); setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton); scene->addItem(this); } ~Circle(){} void Circle::mousePressEvent(QGraphicsSceneMouseEvent *event) { QMessageBox msgBox; string msg{ "Circle " + to_string(Id) + " clicked" }; QString QResult{ QString::fromLatin1(msg.c_str()) }; msgBox.setText( QResult ); msgBox.exec(); } int Id; }; class MainWindow : public QMainWindow { public: QWidget *baseWidget; QGridLayout *baseWidgetGrid; QGraphicsScene *graphicsScene; QGraphicsView *graphicsView; public: MainWindow::MainWindow(QWidget *parent=0) : QMainWindow(parent) { graphicsScene = new QGraphicsScene(0, 0, 120, 120); graphicsScene->addRect( 10, 10, 100, 100 ); new Circle( 1, 20, 20, 20, 20, graphicsScene ); new Circle( 2, 75, 75, 20, 20, graphicsScene ); baseWidget = new QWidget(this); baseWidgetGrid = new QGridLayout(baseWidget); graphicsView = new QGraphicsView(baseWidget); graphicsView->setRenderHint(QPainter::Antialiasing); graphicsView->setScene(graphicsScene); baseWidgetGrid->addWidget(graphicsView, 0, 0, 1, 1); setCentralWidget(baseWidget); } ~MainWindow(){} }; int main(int argc, char *argv[]) { QApplication Application(argc, argv); MainWindow MainWin; MainWin.show(); return Application.exec(); }
-
@JanLaloux said:
so when clicking outside, it would still say
"Circle " bla bla from the msgBox ?I wonder if scene or view need
setMouseTracking(true); -
@JanLaloux said:
so when clicking outside, it would still say
"Circle " bla bla from the msgBox ?I wonder if scene or view need
setMouseTracking(true); -
@mrjj
Yes, wherever you click on the scene you get the messagebox with the ID of the circle that was first clicked. The code I included is "ready to go" if you want to try it.@JanLaloux
Hi , very strange. it said nothing when I clicked. not on circle or outside.update:
Ahh I see that older post used QGraphicsSceneMouseEvent and not QMouseEvent
so just copy & paste error I guess.I then added
protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) { qDebug() << "test"; }
to Circle and now it print test when click on circle but not outside.
So not really sure whats going on.
Does that work for you too?
#include <QApplication> #include <QMessageBox> #include <QtWidgets/QMainWindow> #include <QtWidgets/QGraphicsScene> #include <QtWidgets/QGraphicsView> #include <QtWidgets/QGridLayout> #include <QtWidgets/QGraphicsEllipseItem> #include <qDebug> class Circle : public QGraphicsEllipseItem { public: Circle(const qreal ax, const qreal ay, const qreal wx, const qreal wy, QGraphicsScene *scene) : QGraphicsEllipseItem(ax, ay, wx, wy) { setPen( QPen(QBrush(Qt::black), 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin) ); setBrush( QBrush(Qt::gray) ); setRect(ax, ay, wx, wy); setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton); scene->addItem(this); } ~Circle(){} protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) { qDebug() << "test"; } virtual void mousePressEvent(QMouseEvent *event) { QMessageBox msgBox; QString QResult("DEER"); msgBox.setText( QResult ); msgBox.exec(); } }; class MainWindow : public QMainWindow { public: QWidget *baseWidget; QGridLayout *baseWidgetGrid; QGraphicsScene *graphicsScene; QGraphicsView *graphicsView; public: MainWindow(QWidget *parent=0) : QMainWindow(parent) { graphicsScene = new QGraphicsScene(0, 0, 100, 100); new Circle( 5, 5, 20, 20, graphicsScene ); new Circle( 35, 35, 20, 20, graphicsScene ); new Circle( 65, 65, 20, 20, graphicsScene ); baseWidget = new QWidget(this); baseWidgetGrid = new QGridLayout(baseWidget); graphicsView = new QGraphicsView(baseWidget); graphicsView->setScene(graphicsScene); baseWidgetGrid->addWidget(graphicsView, 0, 0, 1, 1); setCentralWidget(baseWidget); } ~MainWindow(){} }; int main(int argc, char *argv[]) { QApplication Application(argc, argv); MainWindow MainWin; MainWin.show(); return Application.exec(); }
-
It's the
msgBox
that is the culprit!
Replace the qDebug output with the messagebox I used in my code and it goes wrong. The behaviour is as it should without it, I suppose this is a bug...
Remark: it is not needed to make the memberprotected
Anyway, thanks a lot for the help! -
aha!
Pretty strange.ok, its a habit for mousepressed for widgets :)
np. Good with code you can just run :)
-
For people having the same problem that the QMessageBox keeps appearing anywhere you click, you can fix it by ungrabbing the mouse after closing the box:
scene->mouseGrabberItem()->ungrabMouse();
@JanLaloux said in QGraphicsItem to react on CTRL left click:
@mrjj
Yes, wherever you click on the scene you get the messagebox with the ID of the circle that was first clicked. The code I included is "ready to go" if you want to try it.