Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How can my Mouse Press Event differentiate between different items?



  • 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++.


  • Lifetime Qt Champion

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



  • 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


  • Lifetime Qt Champion

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


  • 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?



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



  • 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?



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