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
QtWS25 Last Chance

QGraphicsItem to react on CTRL left click

Scheduled Pinned Locked Moved General and Desktop
18 Posts 5 Posters 4.6k Views
  • 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.
  • J Offline
    J Offline
    JanLaloux
    wrote on 30 Sept 2015, 10:07 last edited by JanLaloux 10 Aug 2015, 08:41
    #1

    I have a QGraphicsScene with different items such a rectangles and circles. It must be possible to click on them in different ways, eg a Control left click, and that should trigger a function call with one or more parameters. What is the best way to achieve this?

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 30 Sept 2015, 10:47 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 2 Oct 2015, 12:39 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
        • M Offline
          M Offline
          mrjj
          Lifetime Qt Champion
          wrote on 2 Oct 2015, 12:51 last edited by mrjj 10 Feb 2015, 12:58
          #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.

          J 1 Reply Last reply 2 Oct 2015, 13:45
          0
          • M mrjj
            2 Oct 2015, 12:51

            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.

            J Offline
            J Offline
            JohanSolo
            wrote on 2 Oct 2015, 13:45 last edited by JohanSolo 10 Feb 2015, 13:45
            #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 2 Oct 2015, 13:46 last edited by
              #6

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

              M 1 Reply Last reply 2 Oct 2015, 13:53
              0
              • J JanLaloux
                2 Oct 2015, 13:46

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

                M Offline
                M Offline
                mrjj
                Lifetime Qt Champion
                wrote on 2 Oct 2015, 13:53 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 2 Oct 2015, 14:04 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!

                  M 1 Reply Last reply 2 Oct 2015, 14:54
                  0
                  • J JanLaloux
                    2 Oct 2015, 14:04

                    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!

                    M Offline
                    M Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on 2 Oct 2015, 14:54 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 2 Oct 2015, 15:05 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 2 Oct 2015, 15:15 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 7 Oct 2015, 16:19 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
                          • M Offline
                            M Offline
                            mrjj
                            Lifetime Qt Champion
                            wrote on 7 Oct 2015, 16:22 last edited by mrjj 10 Jul 2015, 16:39
                            #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 8 Oct 2015, 07:57
                            0
                            • M mrjj
                              7 Oct 2015, 16:22

                              @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 8 Oct 2015, 07:57 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.

                              M 1 Reply Last reply 8 Oct 2015, 08:49
                              0
                              • J JanLaloux
                                8 Oct 2015, 07:57

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

                                M Offline
                                M Offline
                                mrjj
                                Lifetime Qt Champion
                                wrote on 8 Oct 2015, 08:49 last edited by mrjj 10 Aug 2015, 08:54
                                #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 8 Oct 2015, 09:21 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
                                  • M Offline
                                    M Offline
                                    mrjj
                                    Lifetime Qt Champion
                                    wrote on 8 Oct 2015, 09:23 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 31 Jan 2019, 13:58 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