Revsky01
Revsky01

Reputation: 225

How to drag the icon when using drag and drop

Currently I have the following code that executes a drag and drop function and generates a new button by dragging and dropping another.

But what I would like to know is: How can I make an image of him when I drag the mouse button?

something like this:

enter image description here

This is the code you used

In this I would like to obtain the same effect as in the gif previously shown but with the Qpushbutton

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)
        self.create(position)
        e.setDropAction(Qt.MoveAction)
        e.accept()


    def create(self,position):
        print(position)
        self.position  = position
        self.newButton = QPushButton("new",self)
        self.newButton.move(self.position)
        self.newButton.resize(150,50)
        self.newButton.show()



if __name__ == '__main__':

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

Upvotes: 3

Views: 794

Answers (1)

eyllanesc
eyllanesc

Reputation: 243993

You have to take a widget image using the grab() method then set it to QDrag using the setPixmap() method. Also I have created a method that creates a widget of the same type of the source with the same q-properties (that does not imply that it is a copy of the widget since there are non copyable elements). On the other hand it is advisable to use the right click since the left click will interfere with the clicked signal

from PyQt5 import QtCore, QtGui, QtWidgets

def fake_copy_widget(widget, parent):
    t = type(widget)
    w = t(parent)
    mo = widget.metaObject()
    for i in range(mo.propertyCount()):
        prop = mo.property(i)
        if prop.isWritable() and prop.isReadable():
            name = prop.name()
            w.setProperty(name, widget.property(name))
    return w

class Button(QtWidgets.QPushButton):
    def mouseMoveEvent(self, e):
        if e.buttons() & QtCore.Qt.RightButton:
            pos = self.mapFromGlobal(QtGui.QCursor().pos())
            ba = QtCore.QByteArray()
            ds = QtCore.QDataStream(ba, QtCore.QIODevice.WriteOnly)
            ds << pos
            mimeData = QtCore.QMimeData()
            mimeData.setData("application/x-pos", ba)
            pixmap = self.grab()
            drag = QtGui.QDrag(self)
            drag.setHotSpot(pos)
            drag.setPixmap(pixmap)
            drag.setMimeData(mimeData)
            drag.setHotSpot(e.pos() - self.rect().topLeft())
            dropAction = drag.exec_(QtCore.Qt.MoveAction)

class Example(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setAcceptDrops(True)
        button = Button('Button', self)
        button.move(100, 65)
        self.setWindowTitle('Click or Move')
        self.setGeometry(300, 300, 280, 150)

    def dragEnterEvent(self, e):
        if e.mimeData().hasFormat("application/x-pos"):
            e.accept()

    def dropEvent(self, e):
        position = e.pos()
        button = e.source()
        mimedata = e.mimeData()
        p = QtCore.QPoint()
        ba = mimedata.data("application/x-pos")
        ds = QtCore.QDataStream(ba)
        ds >> p
        self.create(QtCore.QRect(position - p, button.size()), button, self)
        e.accept()

    def create(self, geometry, widget, parent):
        button = fake_copy_widget(widget, parent)
        button.setGeometry(geometry)
        button.show()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())

Upvotes: 2

Related Questions