Reputation: 225
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:
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
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