2014-07-05 55 views
2

使用PySide,我构建的作品正是我想要一个可拖动标签:QMimeData:设置和获取正确的MIME类型任意部件

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讨论了测试,获取和设置数据的便利函数,但这些函数用于标准数据类型(例如文本,URL)。我没有找到明确的方法来定义像我的可拖动的QLabel这样的小部件的便利功能。我错过了吗?有没有一种简单的方法来确定我是否在拖拽一个类型为X的小部件?

编辑:我已经尝试了上面相同的代码比QLabels更复杂的小部件,它不起作用。

可能相关的帖子:

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


重要的警告:如果你只是想移动在一个窗口小部件,你不需要调用深奥的拖放机制,但更多的香草事件处理。看到这个: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张贴这也将张贴任何有用的东西在那里。

+0

我刚刚添加到帖子中的重要提示:如果您只是想在窗口中移动窗口小部件,则不需要调用深奥的拖放机制,而是更多的香草事件处理。看到这个:http://stackoverflow.com/questions/12219727/dragging-moving-a-qpushbutton-in-pyqt – neuronet

回答

3

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

docs

QMimeData用于描述能够存储在剪贴板中,并且经由拖动传送的信息和丢弃机制。 QMimeData对象将它们保存的数据与相应的MIME类型相关联,以确保信息可以在应用程序之间安全传输,并在同一应用程序中复制。

如果你正在做一些标准,比如拖/从一个地方下探文本到另一个,你可以使用标准的MIME类型(如使用dragMimeData.setText('your text')或等效dragMimeData.setData('text/plain', 'your text')设置你拖的MIME数据)。然而,由于你正在做一些完全自定义的事情,你应该指定一个自定义的MIME类型,这样你就不会意外地做一些没有意义的事情。

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

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

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

如果您还存储与MIME类型(又名什么,而不是上面'any string you want'人)一些有用的MIME数据,你可以用它来动态地选择,内LabelDrag.dropEvent,该部件这是你想要移动。您可以通过event.mimeData().data('MoveQLabel')访问它。这意味着您的QWidget可以处理移动多个标签,因为它总是会移动正在放置的标签。

+0

@ three_pinapples:谢谢,伟大的东西!不幸的是,我不能只使用mimedat.setData('newtype',self)'。像http://doc.qt.digia.com/qt-maemo/draganddrop-fridgemagnets.html#dragging是需要的,它使用'QByteArray'来定义新的数据类型。我会研究这个(在这个例子中,我还不知道QByteArrays或许多其他的东西)。我会对它进行破解,适当地编辑你的答案,直到我们为未来的编码人员找到一个独立的工作示例,这个示例偶然发现。我还会继续,并将我的完整代码添加到我的问题中,以节省时间。 :) – neuronet

+0

我想,需要像下面这样的东西,但我根本不理解前三行。它看起来像C++比Python更多:O'itemData = QtCore.QByteArray(); dataStream = QtCore.QDataStream(itemData,QtCore.QIODevice.WriteOnly); dataStream << QtCore.QPoint(event.pos() - self.rect()。topLeft()); mimeData = QtCore.QMimeData(); mimeData.setData('x-QLabel',itemData)'任何人都在意在这样的行中编辑,并加上一些注释?我无法在任何地方找到好的文档。你会认为这将是一个普遍而流行的事情。 – neuronet

+1

啊,是的,你是对的。这当然是有道理的,因为你不应该能够在程序之间传递一个对象!我会用更好的解决方案更新答案。 –