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. drag and drop detect source of drag fails
Forum Updated to NodeBB v4.3 + New Features

drag and drop detect source of drag fails

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 4 Posters 565 Views 1 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
    #1

    I have a class Room which holds connections to three neighbor Rooms.

    class Room : public QGraphicsWidget
    {
        Q_OBJECT
    //....
    
    private:
        static constexpr auto mCountOfNeigbours = 3;
    
        std::array<Room *, mCountOfNeigbours> mNeigbours;
    

    No i want to drag and drop the player from one room to another. But only to the neighbour Rooms.

    So i start a drag like this:

    void Room::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        if (QLineF(event->screenPos(), event->buttonDownScreenPos(Qt::LeftButton))
            .length() < QApplication::startDragDistance()) {
            return;
        }
        
        setPlayer(false);
    
        auto drag = new QDrag(event->widget());
        auto mime = new QMimeData;
        drag->setMimeData(mime);
    
        mime->setImageData(playerDraggedImage());
    
        drag->setPixmap(QPixmap::fromImage(playerDraggedImage()));
        drag->setHotSpot(QPoint(0, 0));
    
        auto result = drag->exec();
    
        if (result == Qt::IgnoreAction) {
            setPlayer(true);
        }
    
        setCursor(Qt::OpenHandCursor);
    }
    

    The dragEnterEvent and the dropEvent which should get executed on a neigbour look like this:

    void Room::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
    {
        if ((event->mimeData()->imageData() == playerDraggedImage()) &&
            isNeighbour(event)) {
                event->setAccepted(true);
    
        }
        else {
            event->setAccepted(false);
        }
    }
    
    void Room::dropEvent(QGraphicsSceneDragDropEvent *event)
    {
        if ((event->mimeData()->imageData() == playerDraggedImage()) &&
                isNeighbour(event)) {
             setPlayer(true);
        }
        update();
    }
    

    With a helper which checks if the room is a neigbour of the source room were the drag started:

    bool Room::isNeighbour(QGraphicsSceneDragDropEvent *event) const
    {
        auto room = qobject_cast<Room *>(event->source());
    
        if (room == nullptr) {
            return false;
        }
    
        for(const auto &neighbour : mNeigbours) {
    
            if (room == neighbour) {
                return true;
            }
        }
        return false;
    }
    

    So far so good but it is not working. If i try to find the sender of the drag with

    auto room = qobject_cast<Room *>(event->source());
    

    The result is always zero.

    However i can see were i make the drag:

    auto drag = new QDrag(event->widget());
    

    Here event->widget() has a address, Then why it arrives with nullptr on the target?

    jsulmJ 1 Reply Last reply
    0
    • S sandro4912

      I have a class Room which holds connections to three neighbor Rooms.

      class Room : public QGraphicsWidget
      {
          Q_OBJECT
      //....
      
      private:
          static constexpr auto mCountOfNeigbours = 3;
      
          std::array<Room *, mCountOfNeigbours> mNeigbours;
      

      No i want to drag and drop the player from one room to another. But only to the neighbour Rooms.

      So i start a drag like this:

      void Room::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
      {
          if (QLineF(event->screenPos(), event->buttonDownScreenPos(Qt::LeftButton))
              .length() < QApplication::startDragDistance()) {
              return;
          }
          
          setPlayer(false);
      
          auto drag = new QDrag(event->widget());
          auto mime = new QMimeData;
          drag->setMimeData(mime);
      
          mime->setImageData(playerDraggedImage());
      
          drag->setPixmap(QPixmap::fromImage(playerDraggedImage()));
          drag->setHotSpot(QPoint(0, 0));
      
          auto result = drag->exec();
      
          if (result == Qt::IgnoreAction) {
              setPlayer(true);
          }
      
          setCursor(Qt::OpenHandCursor);
      }
      

      The dragEnterEvent and the dropEvent which should get executed on a neigbour look like this:

      void Room::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
      {
          if ((event->mimeData()->imageData() == playerDraggedImage()) &&
              isNeighbour(event)) {
                  event->setAccepted(true);
      
          }
          else {
              event->setAccepted(false);
          }
      }
      
      void Room::dropEvent(QGraphicsSceneDragDropEvent *event)
      {
          if ((event->mimeData()->imageData() == playerDraggedImage()) &&
                  isNeighbour(event)) {
               setPlayer(true);
          }
          update();
      }
      

      With a helper which checks if the room is a neigbour of the source room were the drag started:

      bool Room::isNeighbour(QGraphicsSceneDragDropEvent *event) const
      {
          auto room = qobject_cast<Room *>(event->source());
      
          if (room == nullptr) {
              return false;
          }
      
          for(const auto &neighbour : mNeigbours) {
      
              if (room == neighbour) {
                  return true;
              }
          }
          return false;
      }
      

      So far so good but it is not working. If i try to find the sender of the drag with

      auto room = qobject_cast<Room *>(event->source());
      

      The result is always zero.

      However i can see were i make the drag:

      auto drag = new QDrag(event->widget());
      

      Here event->widget() has a address, Then why it arrives with nullptr on the target?

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @sandro4912 said in drag and drop detect source of drag fails:

      Here event->widget() has a address

      But is this widget a Room*?
      qobject_cast<Room >(event->source()); will return nullptr if event->source() is not a Room

      https://forum.qt.io/topic/113070/qt-code-of-conduct

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

        Hi,

        Beside @jsulm good remark, you are not accepting the event or the proposed action in your re-implementation of dropEvent.

        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
        3
        • S Offline
          S Offline
          sandro4912
          wrote on last edited by sandro4912
          #4

          The Rooms get put into a QGraphicsScene but i would have expect that QGraphicsSceneMouseEvent *event->widget() is a Room in Room::mouseMoveEvent

          I added the accept like this:

          void Room::dropEvent(QGraphicsSceneDragDropEvent *event)
          {
              if ((event->mimeData()->imageData() == playerDraggedImage()) &&
                      isNeighbour(event)) {
                   setPlayer(true);
                   update();
                   event->setAccepted(true);
              }
              else {
                  event->setAccepted(false);
              }
          }
          

          Is it maybe impossible like i think? Do i have to sublass QMimeData and pass the pointer of the object were the drag was created?

          1 Reply Last reply
          0
          • Christian EhrlicherC Online
            Christian EhrlicherC Online
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @sandro4912 said in drag and drop detect source of drag fails:

            QGraphicsSceneMouseEvent *event->widget()

            So did you actually check it?

            Returns the widget where the event originated,

            I would not expect that a mouse move event's originator is a room object.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

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

              @sandro4912 said in drag and drop detect source of drag fails:

              Is it maybe impossible like i think? Do i have to sublass QMimeData and pass the pointer of the object were the drag was created?

              Yes i checked it and it is not a `Room. I guess i thought it wrongt. So to shorten my question.

              How can you tell in a drop event were the drag was started from?

              Making a custom QMimeData type and passing the Room pointer ?

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

                That's one way yes.

                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
                  #8

                  I solved the issue the pragmatic way:

                  class RoomMimeData : public QMimeData
                  {
                      Q_OBJECT
                  public:
                      void setRoom(Room *room);
                      Room *room() const;
                  
                  private:
                      Room *mRoom;
                  };
                  
                  void Room::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
                  {
                  //...
                      auto drag = new QDrag(event->widget());
                      auto mime = new RoomMimeData;
                      mime->setRoom(this);
                      drag->setMimeData(mime);
                  
                  //..
                  }
                  
                  void Room::dropEvent(QGraphicsSceneDragDropEvent *event)
                  {
                      const auto roomData = qobject_cast<const RoomMimeData *>(event->mimeData());
                      if(roomData && isNeighbour(roomData->room()) &&
                              roomData->imageData() == playerDraggedImage()) {
                           enter();
                           update();
                           event->setAccepted(true);
                      }
                      else {
                          event->setAccepted(false);
                      }
                  }
                  
                  1 Reply Last reply
                  0

                  • Login

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