MousePressEvent in view and items in Qt

10,114

QGraphicsView isn't really a good place to handle scene-specific events. Instead, you'll need to override QGraphicsScene::mousePressEvent. I would recommend something like this:

void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
  if (itemAt(event) == NULL)
  {
    // do stuff if not clicked on an item
  }
  else
  {
    QGraphicsScene::mousePressEvent(event); // this forwards the event to the item
  }
}

Note that QGraphicsScene::itemAt might give you difficulties if you have items with the ItemIgnoresTransformations flag set to true. Look to the docs for QGraphicsScene::itemAt for how to resolve this.

Share:
10,114
fibera
Author by

fibera

Updated on June 09, 2022

Comments

  • fibera
    fibera almost 2 years

    I have a custom QGraphicsView and a custom QGraphicsItem. I want the Item to handle my click if I click in the item, else I want the click to be handled by the View.

    But when I click on the item, the item handles the click. This is ok. But if I click somewhere else the click isn't handled at all. All the code in my classes that have anything to do with mouseEvents is below.

    class CustomView : public QGraphicsView
    {
        Q_OBJECT
    
    public:
    
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
    
    };
    
    void CustomView::mousePressEvent(QGraphicsSceneMouseEvent *event){
        cout << "pressing in view";
    }
    
    class CustomItem : public QGraphicsItem
    {
    public:
        CustomItem(CustomView* widget)
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
    };
    
    CustomItem::CustomItem(CustomView* widget){
        setFlag(ItemIsSelectable);
        setFlag(ItemIsMovable);
    }
    
    void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event){
        cout << "pressing in item";
    }
    

    It seems that when I remove the mousePressEvent function from the CustomItem class and change in the CustomView the mousePressEvent function to:

    void CustomView::mousePressEvent(QMouseEvent *event){
        cout << "pressing in view";
    }
    

    the CustomView handles all the mouseEvents.

    How can I let the CustomItem handles the clicks in the items and the CustomView handle all the other clicks?

    Thank you.

    EDIT

    So now I have changed it to:

        class CustomView : public QGraphicsView
    {
        Q_OBJECT
    
    public:
    
    };
    
     class CustomScene : public QGraphicsScene
    {
    protected:
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
    };
    
    
    void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event){
        cout << "pressing in scene";
    }
    
    class CustomItem : public QGraphicsItem
    {
    public:
        CustomItem(CustomView* widget)
    protected:
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
    };
    
    CustomItem::CustomItem(CustomView* widget){
        setFlag(ItemIsSelectable);
        setFlag(ItemIsMovable);
    }
    
    void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event){
        cout << "pressing in item";
    }
    

    A Click in the scene but not in an item get handled by the scene. But clicks in the items dont get handled by the items itself, instead it get handled by the scene. Unless if you click 2 times really fast on the items it gets handled by the scene and the item.

    Any ideas?

    • Kunal
      Kunal about 12 years
      try overriding QGraphicsScene::mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent ) method in QGraphicsScene, instead of QGraphicsView
    • Anthony
      Anthony about 12 years
      I think your "CustomWidget::mousePressEvent" is supposed to be "CustomView::mousePressEvent" (or vice versa).
    • fibera
      fibera about 12 years
      @Kunal Ty for your input, I moved the mousePressEvent to the scene but I still have a problem with it
    • fibera
      fibera about 12 years
      @Anthony Yes indeed, I changed it in the code. Ty for noticing.
  • fibera
    fibera about 12 years
    Ok, so I removed the QGraphicsView::mousePressEvent(QGraphicsSceneMouseEvent) and added that function to the custom QGraphicsScene. Now if I click somewhere not on an item the scene handles my click. If I click on an item the scene also handles my click. But if I click 2 times very fast on the item, the item and the scene handle my click.
  • Anthony
    Anthony about 12 years
    @fibera I realized a mistake I made in my answer. Try out the edited answer and let me know how it goes.
  • Anthony
    Anthony about 12 years
    @fibera No problem. I just remembered that QGraphicsView also has an itemAt method, so if you wanted, you could ditch the custom QGraphicsScene in favor of your custom QGraphicsView as you were originally trying. However, I still feel that scene-specific events should be handled by QGraphicsScene... it's up to you!