Drag and Drop QLabels with PyQt5
In the case of QLabel
you must create everything from the beginning, for this you can follow the examples of the docs.
In the following example I have placed an example where one class only accepts the drop and the other the drag so that you can see each part and understand better.
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QWidget
from PyQt5.QtGui import QDrag, QPixmap, QPainter, QCursor
from PyQt5.QtCore import QMimeData, Qt
class DraggableLabel(QLabel):
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.drag_start_position = event.pos()
def mouseMoveEvent(self, event):
if not (event.buttons() & Qt.LeftButton):
return
if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
return
drag = QDrag(self)
mimedata = QMimeData()
mimedata.setText(self.text())
drag.setMimeData(mimedata)
pixmap = QPixmap(self.size())
painter = QPainter(pixmap)
painter.drawPixmap(self.rect(), self.grab())
painter.end()
drag.setPixmap(pixmap)
drag.setHotSpot(event.pos())
drag.exec_(Qt.CopyAction | Qt.MoveAction)
class DropLabel(QLabel):
def __init__(self, *args, **kwargs):
QLabel.__init__(self, *args, **kwargs)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if event.mimeData().hasText():
event.acceptProposedAction()
def dropEvent(self, event):
pos = event.pos()
text = event.mimeData().text()
self.setText(text)
event.acceptProposedAction()
class Widget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
label = DropLabel("drop there",self)
label.setGeometry(190, 65, 100,100)
label_to_drag = DraggableLabel("drag this",self)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Update:
Do not confuse the QDrag
with the QMimeData
, if you want to use imageData()
you must set it with setImageData()
as indicated by the docs:
class DraggableLabel(QLabel):
def __init__(self,parent,image):
super(QLabel,self).__init__(parent)
self.setPixmap(QPixmap(image))
self.show()
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.drag_start_position = event.pos()
def mouseMoveEvent(self, event):
if not (event.buttons() & Qt.LeftButton):
return
if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
return
drag = QDrag(self)
mimedata = QMimeData()
mimedata.setText(self.text())
mimedata.setImageData(self.pixmap().toImage())
drag.setMimeData(mimedata)
pixmap = QPixmap(self.size())
painter = QPainter(pixmap)
painter.drawPixmap(self.rect(), self.grab())
painter.end()
drag.setPixmap(pixmap)
drag.setHotSpot(event.pos())
drag.exec_(Qt.CopyAction | Qt.MoveAction)
class my_label(QLabel):
def __init__(self,title,parent):
super().__init__(title,parent)
self.setAcceptDrops(True)
def dragEnterEvent(self,event):
if event.mimeData().hasImage():
print("event accepted")
event.accept()
else:
print("event rejected")
event.ignore()
def dropEvent(self,event):
if event.mimeData().hasImage():
self.setPixmap(QPixmap.fromImage(QImage(event.mimeData().imageData())))
EinderJam
Updated on June 04, 2022Comments
-
EinderJam almost 2 years
I'm trying to drag and drop a Qlabel on another Qlabel with PyQt5:
from PyQt5.QtWidgets import QApplication, QWidget, QToolTip, QPushButton, QMessageBox, QHBoxLayout, QVBoxLayout, QGridLayout,QFrame, QComboBox, QLabel, QLineEdit from PyQt5.QtGui import QIcon, QFont, QPixmap, QImage import sys class my_label(QLabel): def __init__(self,title,parent): super().__init__(title,parent) self.setAcceptDrops(True) def dragEnterEvent(self,event): if event.mimeData().hasFormat("text/plain"): event.accept() else: event.ignore() def dropEvent(self,event): self.setText(event.mimeData().text()) class application(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): label = my_label("drop there",self) label.resize(100,100) label.move(190,65) label_to_drag = QLabel("drag this",self) #label_to_drag.setDragEnabled(True) #doesn't work with QLabel self.show() def closeEvent(self,event): message = QMessageBox.question(self,"Message","Quit ?",QMessageBox.Yes | QMessageBox.No,QMessageBox.No) if message == QMessageBox.Yes: event.accept() else: event.ignore() app = QApplication(sys.argv) fenetre = application() sys.exit(app.exec_())
I wanted to make my first label "draggable",by calling the
setDragEnabled(True)
method (as i was doing for QLineEdit),and drop it on the second label to change his text. Dropping text from another app is working fine,but I can't find how to drag the QLabel inside my own app... What did I miss ?EDIT : modified the code to try to Drag&Drop Images :
class DraggableLabel(QLabel): def __init__(self,parent,image): super(QLabel,self).__init__(parent) self.setPixmap(QPixmap(image)) self.show() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.drag_start_position = event.pos() def mouseMoveEvent(self, event): if not (event.buttons() & Qt.LeftButton): return if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance(): return drag = QDrag(self) mimedata = QMimeData() mimedata.setText(self.text()) drag.setMimeData(mimedata) pixmap = QPixmap(self.size()) painter = QPainter(pixmap) painter.drawPixmap(self.rect(), self.grab()) painter.end() drag.setPixmap(pixmap) drag.setHotSpot(event.pos()) drag.exec_(Qt.CopyAction | Qt.MoveAction) class my_label(QLabel): def __init__(self,title,parent): super().__init__(title,parent) self.setAcceptDrops(True) def dragEnterEvent(self,event): if event.mimeData().hasFormat("text/plain"): print("event accepted") event.accept() else: print("event rejected") event.ignore() def dropEvent(self,event): if event.mimeData().hasImage(): self.setPixmap(QPixmap.fromImage(QImage(event.mimeData().imageData()))) class application(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): label_to_drag = DraggableLabel(self,"index.jpg") label = my_label("drop there",self) label.resize(100,100) label.move(190,65) self.show()
When I drop the
DraggableLabel
(displaying the image) onmy_label
,the event is accepted, buthasImage()
always returns false...Is the way I set the image up wrong ? -
EinderJam almost 6 yearsThanks ! I've another question : I tried to display an image with
setPixmap()
,then drag this image over another label,and make this label display the same image than the first one,but it doesn't work (see edit) -
eyllanesc almost 6 years@EinderJam A QLabel does not show the text or shows the QPixmap, it can not be displayed both. Which edition? If my answer helps you, do not forget to mark it as correct, if you do not know how to do it, review the tour, that is the best way to thank.
-
Elan over 3 yearsvery helpful answer. Thanks +1