1

I try hard to understand how to identify an instance of a class within drag and drop, but i need some help.

Beneath I add a sample from "http://zetcode.com/gui/pyqt5/dragdrop/" to explain.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial

In this program, we can press on a button with a left mouse
click or drag and drop the button with  the right mouse click. 

Author: Jan Bodnar
Website: zetcode.com
Last edited: August 2017
"""

from PyQt5.QtWidgets import QPushButton, QWidget, QApplication
from PyQt5.QtCore import Qt, QMimeData
from PyQt5.QtGui import QDrag
import sys

class Button(QPushButton):

    def __init__(self, title, parent):
        super().__init__(title, parent)


    def mouseMoveEvent(self, e):

        if e.buttons() != Qt.RightButton:
            return

        mimeData = QMimeData()

        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(e.pos() - self.rect().topLeft())

        dropAction = drag.exec_(Qt.MoveAction)


    def mousePressEvent(self, e):

        super().mousePressEvent(e)

        if e.button() == Qt.LeftButton:
            print('press')


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.setAcceptDrops(True)

        self.button = Button('Button', self)
        self.button.move(100, 65)

        self.setWindowTitle('Click or Move')
        self.setGeometry(300, 300, 280, 150)


    def dragEnterEvent(self, e):

        e.accept()


    def dropEvent(self, e):

        position = e.pos()
        self.button.move(position)

        e.setDropAction(Qt.MoveAction)
        e.accept()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    ex.show()
    app.exec_() 

Here my questions:

if I instantiate a 2nd button

    self.button2 = Button('Button2', self)
    self.button2.move(100, 165)

i can also move the button2, but in the DropEvent the first button "button" is moved.

How is it possible to identify within DropEvent, that I move "button2" und place button2?

So: question is: how to identify, which button it is. (i found only drag n drop examples, how to replace a label or a button by another element of same type)

And additional question: to create a new instance works with this type of code. If I create the buttons within QT5 designer, it is not possible to have them as an instance of this type of class Button in this code. So, defining drag n drop in the QT5 designer, drag n drop of an item within a list to another list works, but i am not able to identify, which element I have dragged

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
user3367867
  • 565
  • 1
  • 7
  • 19

2 Answers2

1

If the object you are dragging from is a QWidget then you can get it through the QDropEvent source() method, and the QPushButton is a QWidget so it works in this case:

def dropEvent(self, e):
    if e.source() is not None:
        position = e.pos()
        e.source().move(position)
        e.setDropAction(Qt.MoveAction)
        e.accept()

Remember to verify that it is not None since the source may be another window that is not a QWidget so you would get an exception


If you want the buttons added through Qt Designer you want them to have the same functionality then the easiest solution is to promote the buttons, there are many examples in SO where they show how to do it:

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • this helps me to understand the source. The other way round, I have a source and several buttons from the same class, where i can drop the source, how can i then get the destination similar to e.source? is there something like e.destination? (i know, there is no destination in the documentation? – user3367867 Mar 17 '20 at 15:20
  • @user3367867 The dragEnterEvent method are those that indicate whether an element can be dropped. – eyllanesc Mar 18 '20 at 19:55
0

You are always using self.button in your drop event, so it refers to the same button. Instead you can use QDropEvent.source() to get the correct widget.

def dropEvent(self, e):
    position = e.pos()
    e.source().move(position) # source widget

    e.setDropAction(Qt.MoveAction)
    e.accept()
alec
  • 5,799
  • 1
  • 7
  • 20