Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Qt Academy Launch in California!

    Unsolved How can my Mouse Press Event differentiate between different items?

    General and Desktop
    qgraphicsview c++ qgraphicsitem qmouseevent rectangles
    3
    8
    879
    Loading More Posts
    • 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.
    • M
      MegAmaNeo1 last edited by

      Hello!

      I have trouble dealing with mousepressevents. I have multiple items (rectangles) and want the specific item I click on to react to that click (change its color). The other rectangles should remain unchanged.

      dialog.h:

      class dialog : public QMainWindow
      {
          Q_OBJECT
      
      public:
          dialog(QWidget *parent = nullptr);
          ~dialog();
      
      private:
          Ui::dialog *ui;
      
             QGraphicsScene *scene;
             QGraphicsEllipseItem *ellipse;
             QGraphicsRectItem *rectangle;
             QGraphicsTextItem *text;
      };
      
      class squares : public QGraphicsItem
      {
      public:
          squares();
          QRectF boundingRect() const;
          void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
          bool pressed[10];
          
      protected:
          void mousePressEvent(QGraphicsSceneMouseEvent *event);
          
      };
      

      main.cpp:

      class CustomItem : public QGraphicsRectItem
      {
      protected:
          void mousePressEvent(QGraphicsSceneMouseEvent *event)
          {
      qDebug() << "Custom item clicked.";
          }
      };
      class CustomView : public QGraphicsView
      {
      protected:
          void mousePressEvent(QMouseEvent *event)
          {
              qDebug() << "Custom view clicked.";
              QGraphicsView::mousePressEvent(event);
          }
      };
      
      
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          dialog w;
      QGraphicsScene scene(0, 0, 400, 400);
          CustomItem item[20];
          for (int i = 0; i<10; i++){
              item[i].setRect(10*i, 10, 10, 10);
              scene.addItem(&item[i]);
      }
      
              CustomView view;
                  view.setScene(&scene);
                  view.show();
          return a.exec();
      
      
      }
      

      I added the rectangles via QGraphicsRectItem. As you can see in my dialog.h, I prepared an array of boolean values that stand for each rectangle and describe if its pressed or not. I have seen tutorials and know how to add a mouse event for a single rectangle where it changes its color when you click on it. However I fail to accomplish this for multiple rectangles, where the code is able to differentiate between them and knows that only "this specific one" is clicked.

      Do you have some ideas, maybe small examples to help me go in the right direction? I'm new to Qt and C++.

      jsulm 1 Reply Last reply Reply Quote 0
      • jsulm
        jsulm Lifetime Qt Champion @MegAmaNeo1 last edited by jsulm

        @MegAmaNeo1 I don't understand your code: where do you use squares class?

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply Reply Quote 0
        • M
          MegAmaNeo1 last edited by

          Lol you're right, right now the squares class is unnecessary. I might leave it out overall.
          This is what I meant with being new to Qt :D

          jsulm 1 Reply Last reply Reply Quote 0
          • jsulm
            jsulm Lifetime Qt Champion @MegAmaNeo1 last edited by jsulm

            @MegAmaNeo1 Your custom items could emit a signal in mousePressEvent to notify others that they were pressed.
            Something like:

            for (int i = 0; i<10; i++){
                    item[i].setRect(10*i, 10, 10, 10);
                    scene.addItem(&item[i]);
                    connect(&item, CustomItem::pressed, [this, i] {
                            presssed[i] = true;
                        });
            

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply Reply Quote 2
            • M
              MegAmaNeo1 last edited by

              So if I get it right, this thing:

              connect(&item, CustomItem::pressed, [this, i] {
                              presssed[i] = true;
                          });
              

              checks whether the specific item is pressed and then sets the boolean to true.
              I tried to implement this by putting it in the mousePressEvent function:

              void QGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event){
                  for (int i = 0; i<10; i++){
                      connect(&item, CustomItem::pressed, [this, i] {
                                      pressed[i] = true;
                                  });
                  }
              }
              
              

              But he then says:
              "use of undeclared identifier 'item'"
              "no member named 'pressed' in 'CustomItem'"

              Last one I understand, there is no member 'pressed' in CustomItem class. Did I forget to include some files?

              JonB 1 Reply Last reply Reply Quote 0
              • JonB
                JonB @MegAmaNeo1 last edited by

                @MegAmaNeo1
                This does not address your question per se, but before you go any further: you will not want to put any connect() statement in anything like mousePressEvent(), that would mean creating new signal/slot connections every time the user presses the mouse, not to mention that you are creating 10 of them.... connect()s belong, usually, in somewhere like just after you have created objects....

                1 Reply Last reply Reply Quote 2
                • M
                  MegAmaNeo1 last edited by MegAmaNeo1

                  Thank you, makes sense. I now added it into the for loop where the items are created like jsulm did it above.
                  He still complains about
                  "no member named 'pressed' in 'CustomItem'"
                  and
                  "invalid use of 'this' in non-member function"

                  So I somehow need to add 'pressed' as a member of the CustomItem class I think?

                  JonB 1 Reply Last reply Reply Quote 0
                  • JonB
                    JonB @MegAmaNeo1 last edited by

                    @MegAmaNeo1
                    In @jsulm's outline code you need a signal named pressed in CustomItem for connect(&item, CustomItem::pressed ..., and you also need an array/QVector of bool named pressed for pressed[i]. You'll presumably need to rename one of them. And where he writes void QGraphicsItem::mousePressEvent he means your void CustomItem::mousePressEvent override.

                    1 Reply Last reply Reply Quote 2
                    • First post
                      Last post