Results 1 to 4 of 4

Thread: Design movable menu (buttons) in QGraphicsScene

  1. #1
    Join Date
    Aug 2015
    Posts
    5
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Design movable menu (buttons) in QGraphicsScene

    Hello,

    I'm trying to design a custom menu (made of buttons, not a contextual menu) in a graphics scene.
    I would like to move my menu at the mouse location when somewhere on the graphics scene (but now when I click on one of the buttons).

    Here is an example of what I'm trying to do:
    MenuDesign.png

    My guess is that I need to create a container for my buttons and add it to the scene. Then when I click on the scene somewhere, it moves the container at this location, and when I click on a button it trigger some actions.

    I tried several things (container as a QWidget, as a QGraphicsItemGroup, as a QGraphicsItem) but none of them seems to work as expected, especially when I try to click on one of the buttons, it moves the menu instead of triggering an action.

    Did anyone already tried something like that? Or can someone point me in the right direction (I'm running out of idea) ?

    Here is some questions I'm wondering:
    - Should I use container ? if yes, which one ?
    - Should the buttons in the scene be QPushButton or QGraphicsItems with a button behavior ?
    - Who should handle the buttons clicks ? The button itself ? The containers ? The scene ? The view ?

    Thank you very much.

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Design movable menu (buttons) in QGraphicsScene

    Quote Originally Posted by whiteShadow View Post
    Did anyone already tried something like that? Or can someone point me in the right direction (I'm running out of idea) ?
    A runnable example might help

    Quote Originally Posted by whiteShadow View Post
    Here is some questions I'm wondering:
    - Should I use container ? if yes, which one ?
    Probably QGraphicsItemGroup

    Quote Originally Posted by whiteShadow View Post
    - Should the buttons in the scene be QPushButton or QGraphicsItems with a button behavior ?
    No widgets if you can avoid it, so QGraphicsItem based

    Quote Originally Posted by whiteShadow View Post
    - Who should handle the buttons clicks ? The button itself ? The containers ? The scene ? The view ?
    I'd say the button.

    Cheers,
    _

  3. #3
    Join Date
    Aug 2015
    Posts
    5
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Design movable menu (buttons) in QGraphicsScene

    Unfortunately I'm not allowed to disclose the code but I will try maybe to create something similar on a dummy project to show you.

    May I ask you why you said to avoid widgets ?
    My first thought was that even if it is a custom menu, buttons are still buttons. Why not using QPushButton then ?

    Thank you very much for your help.
    Last edited by whiteShadow; 10th November 2015 at 17:55.

  4. #4
    Join Date
    Aug 2015
    Posts
    5
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Design movable menu (buttons) in QGraphicsScene

    Thanks to anda_skoa, I finally find a way to do it.

    I don't think it's the best way but it works.

    For those having the same issue here is what I did:

    I changed my menu buttons from QPushButton to QGraphicsObject. In my buttons constructor, I set setAcceptHoverEvents(true) to be able to change button color when mouse hover them (I check in the paint() if option.state has the QStyle::State_MouseOver flag on and change Brush if it has).
    I also set the flag ItemIgnoresTransformation because I don't want my buttons to be zoomed in or move when the scene is transformed (but still I can move then programmatically if I want to position them somewhere else on my scene).
    Then I defined boundingRect(), paint() and mousePressEvent(). mousePressEvent accept the event (e->accept()) and emit a signal in my case, because I want to connect my button to slots (which is why I subclassed a QGraphicsObject and not a QGraphicsItem. It's not as good performance wise, but I have a small scene, so it should be fine).

    Then I created a container for these buttons. This class subclass QObject (I wanted some signals/slots here too) AND QGraphicsItemGroup.
    In this constructor I set setHandlesChildEvents(false) because this is just a container, and I want my buttons inside to receive the actual event.

    Finally in my scene, I create a new container, add it to the scene, and created+added buttons in the container. Then I overloaded mousePressEvent in my scene to detect if a click happened on a QGraphicsItem or not. If it's not the case, I accept the event to avoid propagation to other widget, and I do what I have to do when a click on my scene happen.
    If a QGraphicsItem has been clicked, then I just call the QGraphicsScene::mousePressEvent to propagate the events to children (then my container will ignore it because I asked him not to handle child events, and finally the buttons will accept it and react by emit a signal).

    Here is my customScene::mousePressEvent (it's probably not the best way to implement it, so if anyone has some suggestions to improve it, I'll take'em !!! ):

    Qt Code:
    1. void customScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
    2. {
    3. if (event->button() == Qt::LeftButton)
    4. {
    5. QGraphicsItem* item = this->itemAt(event->scenePos(), QTransform());
    6.  
    7. if (!item)
    8. {
    9. // No graphics item has been clicked. The scene handle the event then.
    10. event->accept();
    11.  
    12. // Move probes center
    13. this->centerCrosshair->setPos(event->scenePos());
    14. this->centerCrosshair->show();
    15.  
    16. // Move menu
    17. this->menu->setMenuCenter(event->scenePos().x(), event->scenePos().y());
    18. this->menu->show();
    19.  
    20. // Move pattern
    21. for (int i = 0; i < this->pat.size(); ++i)
    22. {
    23. this->pat[i]->setCenter(event->scenePos().x(), event->scenePos().y());
    24. }
    25. }
    26. }
    27.  
    28. QGraphicsScene::mousePressEvent(event);
    29. }
    To copy to clipboard, switch view to plain text mode 

    I hope this could help some people trying to do the same thing. I spent a couple of days trying to figure this out. Now I read it, it seems trivial, but when you don't know, it's not.

    If anyone has comments or suggestions to improve it, I'd be happy to ear them.

    Thank you.

Similar Threads

  1. Design buttons with custom shapes
    By LuisLoez89 in forum Qt Programming
    Replies: 7
    Last Post: 22nd April 2015, 16:36
  2. QGraphicsScene & QGraphicsView design decisions
    By hayzel in forum Qt Programming
    Replies: 2
    Last Post: 26th December 2014, 18:05
  3. Replies: 5
    Last Post: 29th November 2012, 15:26
  4. Replies: 0
    Last Post: 14th February 2012, 11:03
  5. Context Menu Design
    By qtoptus in forum Qt Programming
    Replies: 0
    Last Post: 6th April 2010, 17:41

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.