QMimeData: Configuring and Getting the Right MIME Types for Custom Widgets

Using PySide, I create a drag-and-drop shortcut that works exactly the way I want:

class DraggableLabel(QtGui.QLabel): def __init__(self, txt, parent): QtGui.QLabel.__init__(self, txt, parent) self.setStyleSheet("QLabel { background-color: rgb(255, 255, 0)}") def mouseMoveEvent(self, event): drag=QtGui.QDrag(self) dragMimeData=QtCore.QMimeData() drag.setMimeData(dragMimeData) drag.exec_(QtCore.Qt.MoveAction) 

(Note that a complete example that uses a DraggableLabel is inserted below). Unfortunately, I do not understand what is happening with QMimeData , and I'm afraid that I will run into big problems when I use the same code in real examples.

In particular, I am concerned that my reimplementation of mouseMoveEvent creates an instance of QMimeData without the argument passed: QtCore.QMimeData() . This is normal? In more complex widgets, I will be fine if I continue to do this in the appropriate event handler: will the program automatically create the correct type of MIME data for drag and drop?

The reason I am afraid that I am missing something is because in the Qt drag and drop documentation , it has lines of code like:

 mimeData -> setText(commentEdit->toPlainText()); 

which apparently doesn’t seem to like it, just letting the program take care of things as part of the redefinition of the event handler.

In addition, the QMimeData Documentation discusses convenient features for testing, retrieving, and setting data, but they are for standard data types (e.g. text, URLs). I did not find a clear way to define such convenient functions for widgets like my draggable QLabel . Am I missing this? Is there an easy way to find out if I am dragging a widget like X?

Edit: I tried the same code with much more complex widgets than QLabels, and it does not work.

Potentially relevant posts:

Drag and Drop QWidget in QT 5
How to drag custom widgets?
https://stackoverflow.com/questions/18272650/fill-the-system-clipboard-with-data-of-custom-mime-type Python object in QMimeData


An important warning: if you just want to move the widget out of the window, you don’t need to call esoteric drag mechanisms, but more handling vanilla events. See this: Drag / Drop QPushButton in PyQt .


The full working code of the standalone code, which includes the following:

 # -*- coding: utf-8 -*- from PySide import QtGui, QtCore class LabelDrag(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.initUI() def initUI(self): self.lbl=DraggableLabel("Drag me", self) self.setAcceptDrops(True) self.setGeometry(40,50,200,200) self.show() def dragEnterEvent(self,event): event.accept() def dropEvent(self, event): self.lbl.move(event.pos()) #moves label to position once the movement finishes (dropped) event.accept() class DraggableLabel(QtGui.QLabel): def __init__(self, txt, parent): QtGui.QLabel.__init__(self, txt, parent) self.setStyleSheet("QLabel { background-color: rgb(255, 255, 0)}") def mouseMoveEvent(self, event): drag=QtGui.QDrag(self) dragMimeData=QtCore.QMimeData() drag.setMimeData(dragMimeData) drag.exec_(QtCore.Qt.MoveAction) def main(): import sys qt_app=QtGui.QApplication(sys.argv) myMover=LabelDrag() sys.exit(qt_app.exec_()) if __name__=="__main__": main() 

Note. I post this on QtCentre , post something useful from there.

+2
source share
1 answer

In my experience, MimeData is used to filter drag and drop operations so that the action really makes sense. For example, you cannot drag QLabel into the middle of QTextEdit or the address bar of the browser or desktop of your computer.

From docs :

QMimeData is used to describe information that can be stored on the clipboard, and transmitted using the drag and drop mechanism. QMimeData objects associate the data they store with the corresponding MIME types to ensure secure transfer of information between applications and copying within the same application.

If you were doing something standard, such as dragging / dropping text from one place to another, you would use one of the standard MIME types (for example, setting the drag and drop MIME data using dragMimeData.setText('your text') or equivalent to dragMimeData.setData('text/plain', 'your text') ). However, since you are doing something completely ordinary, you should probably specify a custom MIME type so that you cannot accidentally do something that does not make sense.

So, I would set the MIME data to something like dragMimeData.setData('MoveQLabel', QByteArray('any string you want')) , which stores an arbitrary string for the MIME type MoveQLabel . This arbitrary string can be used to find the widget that you want to move at the end of the drag (perhaps by saving its position?).

You have to change your LabelDrag class above to check the MIME type of the event (use event.mimeData() to get the QMimeData object that you set when you started the drag) and accept or reject the event depending on whether the MIME type matches MoveQLabel (or whatever you call your custom MIME type). This should be done in both dragEnterEvent and dropEvent . The code will look something like this:

 def dragEnterEvent(self, event): # you may also need to check that event.mimeData() returns a valid QMimeData object if event.mimeData().hasFormat('MoveQLabel'): event.accept() else: event.reject() 

If you also save some useful MIME data with a MIME type (otherwise something instead of 'any string you want' above), you can use it to dynamically select inside LabelDrag.dropEvent which widget you want to move. You can access it through event.mimeData().data('MoveQLabel') . This means that your QWidget can handle the movement of multiple tags, as it will always move the one that is discarded.

+3
source

Source: https://habr.com/ru/post/951964/


All Articles