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.
  • J Offline
    J Offline
    JanLaloux
    wrote on last edited by JanLaloux
    #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
    • 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