QMimeData:为任意小部件设置和获取正确的MIME类型

时间:2014-07-05 02:17:00

标签: qt pyqt mime-types pyside

使用PySide,我构建了一个可拖动的标签,它可以完全按照我的要求运行:

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)

(注意下面粘贴使用DraggableLabel的完整示例)。不幸的是,我不明白QMimeData发生了什么,并担心当我在现实世界的例子中使用类似的代码时,我会遇到大问题。

特别是,我担心我重新实现mouseMoveEvent会创建一个QMimeData的实例,而不会传递任何参数:QtCore.QMimeData()。这是正常的吗?在更复杂的小部件中,如果我在相关的事件处理程序中继续这样做,我会好的:程序会自动创建正确类型的MIME数据进行拖放吗?

我害怕失去某些东西的原因是因为在Qt Drag and Drop documentation,它有如下代码行:

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

似乎就像让程序在事件处理程序的重新实现中处理事情一样。

此外,QMimeData Documentation讨论了测试,获取和设置数据的便捷功能,但这些功能适用于标准数据类型(例如,文本,网址)。我没有找到明确的方法为像我的可拖动QLabel这样的小部件定义这样的便利功能。我错过了吗?有没有一种简单的方法可以找出我是否在拖动X型小部件?

编辑:我尝试使用上面相同的代码,使用比QLabel更复杂的小部件,但它不起作用。

潜在相关的帖子:

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


重要提示:如果您只想在窗口中移动窗口小部件,则无需调用深奥的拖放机制,而是需要更多的vanilla事件处理。见:Dragging/Moving a QPushButton in PyQt


完整的自包含代码示例,其中包含以上内容:

# -*- 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()

注意我也会在QtCentre张贴此内容,并会发布有用的内容。

1 个答案:

答案 0 :(得分:3)

根据我的经验,MimeData用于过滤拖放操作,以便操作实际上有意义。例如,您不应该将QLabel拖到QTextEdit或浏览器地址栏或计算机桌面的中间。

来自docs

  

QMimeData用于描述可以存储在剪贴板中并通过拖放机制传输的信息。 QMimeData对象将它们持有的数据与相应的MIME类型相关联,以确保信息可以在应用程序之间安全地传输,并在同一个应用程序中进行复制。

如果你正在做一些标准的事情,比如将文本从一个地方拖放到另一个地方,你可以使用一种标准的MIME类型(比如使用dragMimeData.setText('your text')设置拖动的MIME数据或等效{{1 }})。但是,由于您正在做一些完全自定义的事情,您应该指定一个自定义MIME类型,这样您就不会意外地做一些没有意义的事情。

所以我会将MIME数据设置为类似dragMimeData.setData('text/plain', 'your text')的内容,它存储MIME类型dragMimeData.setData('MoveQLabel', QByteArray('any string you want'))的任意字符串。这个任意字符串可用于在拖动结束时查找要移动的小部件(可能是通过存储它的位置?)。

您应修改上面的MoveQLabel类以检查事件的MIME类型(使用LabelDrag获取您在开始拖动时设置的event.mimeData()对象),并接受或拒绝该事件取决于MIME类型是否匹配QMimeData(或任何您称为自定义MIME类型)。这应该在MoveQLabeldragEnterEvent方法中完成。 您的代码看起来像:

dropEvent

如果您还存储了一些MIME类型的有用MIME数据(也就是上面的其他内容而不是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() ),您可以使用它在'any string you want'内动态选择哪个小部件是您的想搬家。您可以通过LabelDrag.dropEvent访问它。这意味着您的event.mimeData().data('MoveQLabel')可以处理移动多个标签,因为它始终会移动正在丢弃的标签。