Drag and Drop QLabels with PyQt5

2024/9/20 5:49:59

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 sysclass 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):returnif (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():returndrag = 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) on my_label,the event is accepted, but hasImage() always returns false...Is the way I set the image up wrong ?

Answer

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 sysfrom PyQt5.QtWidgets import QApplication, QLabel, QWidget
from PyQt5.QtGui import QDrag, QPixmap, QPainter, QCursor
from PyQt5.QtCore import QMimeData, Qtclass 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):returnif (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():returndrag = 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):returnif (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():returndrag = 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())))
https://en.xdnf.cn/q/72386.html

Related Q&A

replace block within {{ super() }}

I have a base template which includes a block for the default <head> content. Within the head block, theres a block for the <title>.For example, in the base file I would have:<head>{%…

Change Timezone for Date object Python

Hello I am using Pythonanywhere and when I call from datetime import *print date.today().dayIt is printing a different day than the day it is where I live (Austin, Texas). I figured it is because there…

Multiprocessing Pool - how to cancel all running processes if one returns the desired result?

Given the following Python code: import multiprocessingdef unique(somelist):return len(set(somelist)) == len(somelist)if __name__ == __main__:somelist = [[1,2,3,4,5,6,7,8,9,10,11,12,13,2], [1,2,3,4,5],…

Pandas: Product of specific columns

Finding the product of all columns in a dataframe is easy:df[Product] = df.product(axis=1)How can I specify which column names (not column numbers) to include in the product operation?From the help pa…

instagram.bind.InstagramClientError: Unable to parse response, not valid JSON

Made myself a simple Instagram client to make authenticated requests to their API. However, running it keeps throwing the following errorTraceback (most recent call last):File "request-ig-data.py&…

Using jinja to send data to Javascript

I have Python code, in which Im using jinja to send data to a template in Flask. I can access the code just find in HTML, but when I try displaying the data in Javascript, it doesnt work. For example, …

celery: Substantial drift from

I have quite a problem with celery on my distribted system. I have couple of machines among different localizations and Ive got a lot of warnings in my log files like:"Substantial drift from celer…

jinja2 link to static files

I am trying to understand how to create a link to static files in jinja2.Everything I look up relates to Flask whereas I am using just webapp2 at this stage.My main.py file looks as follows:import os i…

How to upgrade tensorflow with GPU on google colaboratory

Currently google colaboratory uses tensorflow 1.4.1. I want to upgrade it to 1.5.0 version. Each time when i executed !pip install --upgrade tensorflow command, notebook instance succesfully upgrades t…

How to print warnings and errors when using setuptools (pip)

I am using setuptools to package code such that it can be easily installed using cd project_name && pip install .During the setup process, I want to warn the user about pre-existing config file…