Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicsItem to react on CTRL left click
Forum Updated to NodeBB v4.3 + New Features

QGraphicsItem to react on CTRL left click

Scheduled Pinned Locked Moved General and Desktop
18 Posts 5 Posters 4.6k Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mrjjM Offline
    mrjjM Offline
    mrjj
    Lifetime Qt Champion
    wrote on last edited by
    #2

    hi
    if you override mousePressEvent(QMouseEvent *event)
    you can check for ctrl there

    virtual void mousePressEvent(QMouseEvent *event) {
    if (event->modifiers() == Qt::ControlModifier && event->button() == Qt::LeftButton)
    call whatever
    }
    

    you can do that for
    QGraphicsItem or QGraphicsScene depending on your needs.
    see
    http://www.qtforum.org/article/20343/qgraphicsscenemouseevent-event-has-no-value.html
    for code sample.
    Note the use of scenePos() and not Pos()

    You can use QGraphicsScene::itemAt to find out which items was under mouse.

    1 Reply Last reply
    1
    • J Offline
      J Offline
      JanLaloux
      wrote on last edited by
      #3

      I tried the approach but it seems not working. I made a simple example with a class Circle that inherts from QGraphicsEllipseItem. Clicking on a circle does not trigger the Circle::mousePressEvent(). What am I missing?

      #include <QApplication>
      #include <QMessageBox>
      #include <QtWidgets/QMainWindow>
      #include <QtWidgets/QGraphicsScene>
      #include <QtWidgets/QGraphicsView>
      #include <QtWidgets/QGridLayout>
      #include <QtWidgets/QGraphicsEllipseItem>
      
      class Circle : public QGraphicsEllipseItem {
      public:
      	Circle::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(){}
      
      	void Circle::mousePressEvent(QMouseEvent *event) {
      		QMessageBox msgBox;
      		QString QResult{ QString::fromLatin1("Circle clicked") };
      		msgBox.setText( QResult );
      		msgBox.exec();
      	}
      };
      
      
      
      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, 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();
      }
      
      
      1 Reply Last reply
      0
      • mrjjM Offline
        mrjjM Offline
        mrjj
        Lifetime Qt Champion
        wrote on last edited by mrjj
        #4

        Hmmm, you have listed it under public:
        Try move it to
        protected:
        Also normally its virtual

        so try with

        protected: virtual void Circle::mousePressEvent(QMouseEvent *event) { .. }

        note:
        you can remove the Circle:: when the function is implemented in the .H file.

        JohanSoloJ 1 Reply Last reply
        0
        • mrjjM mrjj

          Hmmm, you have listed it under public:
          Try move it to
          protected:
          Also normally its virtual

          so try with

          protected: virtual void Circle::mousePressEvent(QMouseEvent *event) { .. }

          note:
          you can remove the Circle:: when the function is implemented in the .H file.

          JohanSoloJ Offline
          JohanSoloJ Offline
          JohanSolo
          wrote on last edited by JohanSolo
          #5

          @mrjj said:

          Also normally its virtual

          so try with

          protected: virtual void Circle::mousePressEvent(QMouseEvent *event) { .. }

          From a purely technical point of view, the virtual is not necessary when reimplementing a virtual method, the `virtualness' is inherited from the base class. I therefore don't think this should help.

          `They did not know it was impossible, so they did it.'
          -- Mark Twain

          1 Reply Last reply
          0
          • J Offline
            J Offline
            JanLaloux
            wrote on last edited by
            #6

            No help, not with protected: nor protected: virtual ...

            mrjjM 1 Reply Last reply
            0
            • J JanLaloux

              No help, not with protected: nor protected: virtual ...

              mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #7

              @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.

              1 Reply Last reply
              0
              • J Offline
                J Offline
                JanLaloux
                wrote on last edited by
                #8

                I noticed in Chip that the event passed is of type QGraphicsSceneMouseEvent * instead of QMouseEvent *. Changed it and now it works, even as public. Thanks for the support!

                mrjjM 1 Reply Last reply
                0
                • J JanLaloux

                  I noticed in Chip that the event passed is of type QGraphicsSceneMouseEvent * instead of QMouseEvent *. Changed it and now it works, even as public. Thanks for the support!

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by
                  #9

                  @JanLaloux
                  Good spotted! :)

                  1 Reply Last reply
                  0
                  • Chris KawaC Offline
                    Chris KawaC Offline
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on last edited by
                    #10

                    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.

                    1 Reply Last reply
                    0
                    • J Offline
                      J Offline
                      JanLaloux
                      wrote on last edited by
                      #11

                      OK, now I understand the meaning of the Q_DECL_OVERRIDE macro I used to see in the examples...

                      1 Reply Last reply
                      0
                      • J Offline
                        J Offline
                        JanLaloux
                        wrote on last edited by
                        #12

                        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();
                        }
                        
                        1 Reply Last reply
                        0
                        • mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on last edited by mrjj
                          #13

                          @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);

                          J 1 Reply Last reply
                          0
                          • mrjjM mrjj

                            @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);

                            J Offline
                            J Offline
                            JanLaloux
                            wrote on last edited by
                            #14

                            @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.

                            mrjjM 1 Reply Last reply
                            0
                            • J JanLaloux

                              @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.

                              mrjjM Offline
                              mrjjM Offline
                              mrjj
                              Lifetime Qt Champion
                              wrote on last edited by mrjj
                              #15

                              @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();
                              }
                              
                              1 Reply Last reply
                              0
                              • J Offline
                                J Offline
                                JanLaloux
                                wrote on last edited by
                                #16

                                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 member protected
                                Anyway, thanks a lot for the help!

                                1 Reply Last reply
                                0
                                • mrjjM Offline
                                  mrjjM Offline
                                  mrjj
                                  Lifetime Qt Champion
                                  wrote on last edited by
                                  #17

                                  aha!
                                  Pretty strange.

                                  ok, its a habit for mousepressed for widgets :)

                                  np. Good with code you can just run :)

                                  1 Reply Last reply
                                  0
                                  • W Offline
                                    W Offline
                                    willems1994
                                    wrote on last edited by
                                    #18

                                    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.

                                    1 Reply Last reply
                                    2

                                    • Login

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • Users
                                    • Groups
                                    • Search
                                    • Get Qt Extensions
                                    • Unsolved