Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicScene/QGraphicsWidget: How to do complex movements over several Widgets
Qt 6.11 is out! See what's new in the release blog

QGraphicScene/QGraphicsWidget: How to do complex movements over several Widgets

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 3 Posters 487 Views 2 Watching
  • 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.
  • S Offline
    S Offline
    sandro4912
    wrote on last edited by sandro4912
    #1

    I have several Rooms which are derrived from QGraphicsWidget.

    These Room widgets are added to a QGraphicsScene.

    Now I want to do the following.

    Hold down the right mouse button on a Room.

    Hold it down until I reach the destination Room.

    While hold down I can hover over more rooms and trigger certain actions (like call a function which changes theire appearance) when hover over them until I reach my destination rooms.

    When I reach the final room and release the right button some action should be toggled which affects all the rooms I hit on the way. So I need to keep track of which room I passed.

    If I don't reach the final room (release out of room widget). All Actions get reversed.

    Whats the easiest way to achieve what I described?

    Do I have to write a custom event filter? Like it was done with this similar issue:
    https://forum.qt.io/topic/107430/detect-if-mouse-buttons-are-pressed-when-sliding-into-widget/2
    (But there I used QWidget instead of QGraphicsScene).

    Can I just derrive QGraphicsScene and handle the mouseevents there?

    I first had the stupid idea of using QDrag with a Custom QMimeData which keeps track of the passed widgets but that does not seem to work. I think drag and drop actions work only between two widgets directly right?

    Im looking forward to hear youre opinion.

    Let me know if something is unclear.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      That's something you should rather do at the QGraphicsView level since it's what is showing your Rooms. You will likely be interested in the mouseMoveEvent and friends.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • S Offline
        S Offline
        sandro4912
        wrote on last edited by
        #3

        Thanks for the hint to the View. The approach works well. I figured out with qgraphicsitem_cast and itemAt I can always identify which widget is clicked.

        So far my code looks like this (could be still buggy)

        
        void DungeonView::mousePressEvent(QMouseEvent *event)
        {
            if (event->button() == Qt::RightButton) {
                if (auto room = qgraphicsitem_cast<Room *>(itemAt(event->pos())) ;
                        room->hasPlayer()) {
                    mShootArrowSelectOn = true;
        
                    room->setTarget(true);
                    mlastRoom = room;
                    mMarkedRooms.push_back(room);
        
                    setCursor(Qt::CrossCursor);
                    return;
                }
            }
            // forward to handle drag and drop when left Button is pressed
            QGraphicsView::mousePressEvent(event);
        }
        
        void DungeonView::mouseReleaseEvent(QMouseEvent *event)
        {
            if (mShootArrowSelectOn && event->button() == Qt::RightButton) {
                for (auto &room : mMarkedRooms) {
                    room->setTarget(false);
                    
                    // do action here
                }
        
                mMarkedRooms.clear();
                mlastRoom = nullptr;
        
                mShootArrowSelectOn = false;
                setCursor(Qt::ArrowCursor);
            }
            else {
                // forward to handle drag and drop when left Button is pressed
                QGraphicsView::mouseReleaseEvent(event);
            }
        }
        
        void DungeonView::mouseMoveEvent(QMouseEvent *event)
        {
            auto room = qgraphicsitem_cast<Room *>(itemAt(event->pos()));
        
            if(room == nullptr) {
                if(!mShootArrowSelectOn && mlastRoom != nullptr) {
                    setCursor(Qt::ArrowCursor);
                }
                // forward to handle drag and drop when left Button is pressed
                QGraphicsView::mouseMoveEvent(event);
                return;
            }
        
            if(room == mlastRoom) {
                // forward to handle drag and drop when left Button is pressed
                QGraphicsView::mouseMoveEvent(event);
                return;
            }
        
            if (mShootArrowSelectOn && !maxArrowRangeReached() &&
                    isNeigbourOfLastMarkedRoom(room)) {
        
                room->setTarget(true);
                mMarkedRooms.push_back(room);
                mlastRoom = room;
            }
            else {
                // forward to handle drag and drop when left Button is pressed
                QGraphicsView::mouseMoveEvent(event);
            }
        }
        

        Now this gives annother question. As you can see in the comments currently I forward my actions to the QGraphicsView functions. Reasons for this is they forward the events to the Room widgets to perform a drag and drop Operation with them.

        Is it a good idea to make the drag and drop in the Room then? Or should I also move it "up" to QGraphicsView ?

        1 Reply Last reply
        0
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi
          Nothing bad in forwarding to base class.
          and in many cases required as not to break functionality.
          handling DnD in room seems perfectly valid as it hold the needed info
          but only you can say if it fits better in a level above.

          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved