使用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张贴此内容,并会发布有用的内容。
答案 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类型)。这应该在MoveQLabel
和dragEnterEvent
方法中完成。
您的代码看起来像:
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')
可以处理移动多个标签,因为它始终会移动正在丢弃的标签。