Important: Please read the Qt Code of Conduct -

[SOLVED] QGraphicsItem not accepting mouse buttons disables selection

  • I'm sorry if this is an RTFM question but I couldn't find the answer

    While using the QGraphicsScene framework with some custom items and wanted to work on selection those.

    For various reasons (such as having different tools available to the user) I don't want to handle the selection in QGraphicsItem's mouse pressed event, but rather in the scene's one.

    The problem is that if I set accepted mouse buttons to 0 on the item setSelected stops working.

    Item's constructor:

    @DeviceElement::DeviceElement(QGraphicsItem *parent) :

    Relevant part of scene's event handler:

    @case Mode::Select:
    if(button == Qt::LeftButton){
    if(! (mouseEvent->modifiers() | Qt::ControlModifier)){
    auto elit = itemAt(mouseEvent->scenePos(), QTransform());
    qDebug () << "DeviceScene::mousePressEvent elit ==" << elit;
    if(elit != nullptr){

    The dual inheritance from QObject and QGraphicsItem is a refactoring hiccup I'm set to change later

  • setAcceptedMouseButtons(0); switches off all buttons, as far as I understand TFM :-)

  • Yes, it does, but only for the item - the press is properly received in the scene (second snippet in OP) and I get the proper item from that itemAt call.

    But setSelected doesn't work and to my understanding it should, regardless of what buttons are accepted. Or maybe it is tied with the item being a mouse grabber?

  • The item may need setFlag(ItemIsFocusable); as well.

  • Possible, but unlikely: focusability is about keyboard input, like you would have a custom textfield as an item. Plus it could introduce issues with hotkeys.

    Also, I've just seen the selection works, but the item is just as soon deselected - it receives a selected(true) and then selected(false) on each click. And I am 100% sure I only send it once.

  • You could set a breakpoint in the "QGraphicsItem::setSelected" routine and see in the stack trace where the second call comes from.

  • It seems as though calling QEvent::ignore on the event passed to mouse press event issues setSelected(false)

    Seems we posted at the same time - that's what qDebug() output seems to indicate.

    And I haven't built Qt from source and setSelected is not virtual.

    1. You click on an item with the left mouse button to select it. Right?

    2. You switch off that the item re-acts to clicks with the left (in fact any) mouse button. So the Qt thinks it should not select the item when you click.

    3. But you catch the click event and to try to explicitly select it yourself.

    I would think you use the system in a way that it is not designed for: on the one hand say Qt it should not select an item and on the other hand you want it selected anyway.

    It's a puzzle where classical SF-robots die with smoking heads.

  • You got that right. I wanted to avoid some additional coupling in items having to check the scene's mode (that's where user's selected tool is) but I guess it was a misguided attempt.

    Since I'm NOT going to try and change Qt (damn, haven't even compiled it myself yet) I guess I'll just have to feed the items with pointers back to the scene and just check that mode.

    Thank you for your time.

  • You could add a pointer to this mode to the graphics item's "data" field, see QGraphicsItem::setData(), when you add the item to the scene.

  • It's a custom class hierarchy, all inheriting QGraphicsItem, so I can as well store the pointer as a private member, not that it matters really.


    Turns out I had a call to QGraphicsScene::mousePressEvent at the bottom of my CustomScene::mousePressScene and that was what did that default selection stuff. Although "TFM": suggests it's enough to override the item's event handler:

    bq. The default implementation handles basic item interaction, such as selection and moving. If you want to keep the base implementation when reimplementing this function, call QGraphicsItem::mousePressEvent() in your reimplementation.

    Well, easy to miss the bugger at over 100 lines of a function and once again thanks for help :)

Log in to reply