PyQt: 拖放事件(Drag & Drop)
拖放,通过拖拽一个或者多个对象来完成相应的移动、复制等操作。拖放在我们使用的程序应用中是一个非常常见的操作,也是一个非常实用的操作。
MIME
Pyqt的拖放事件是基于MIME的拖放。QMimeData对象存储着相关的数据并对应着某种MIME类型,该对象存储在剪贴板上以便应用于拖放过程。
QMimeData类的函数支持一些MIME类型的检测。
Tester | Getter | Setter | MIME Types |
---|---|---|---|
hasText() | text() | setText() | text/plain |
hasHtml() | html() | setHtml() | text/html |
hasUrls() | urls() | setUrls() | text/uri-list |
hasImage() | imageData() | setImageData() | image/ * |
hasColor() | colorData() | setColorData() | application/x-color |
拖放事件并不仅仅局限于处理文本和图像数据,任何类型的数据都可以在拖放操作中进行传递。为了可以在不同的应用中“拖”信息,这些应用必须标明他们可以接受或者产生哪些类型的数据。而MIME 类型就可以满足这一要求。QDrag
对象在构建的时候就包含了一个MIME类型的列表来表征数据,且被接受的部件对象会利用这个来获取数据。对于通用的数据类型,可以非常方便地使用上述函数来进行处理,而对于用户自定义数据类型,则很有必要进行显式的声明。
为了支持额外的媒体类型(media type), 可以简单的通过QMimeData
对象的setData()
函数来进行数据的设置。该函数可以适用于所有的MIME类型和包含合适数据类型的QByteArray
对象。
拖放行为
pyqt中的很多widget都支持拖放事件,而拖放事件也有好几个重要的类。
QDrag
:支持基于MIME的拖放数据转移器。
DragEnterEvent
: 当被拖动的对象移动到可以可以接受操作的widget时会触发该方法。
DragMoveEvent
:当拖放操作在执行过程中触发。
DragLeaveEvent
:当拖放操作离开当前widget时触发。
DropEvent
:当拖放操作结束时触发。
Note: 以上的触发前置条件是当前区域(widget)可以接受拖放,这个可以通过setAccepteDrops(True)函数来激活。
在最简单的例子中,拖放行为的目标(target)会接收一份被“拖”对象的copy,并且数据的“源”会考虑是不是删除原始数据,而这一个结果将由CopyAction
行为决定。当然,target也会处理其他类型的行为,如MoveAction
、LinkAction
等行为。如果“源”(source)调用QDrag
对象的exec()
并且返回一个MoveAction
,那么“源”就需要自己选择是否删除原始数据。被源部件创建的QMimeData
和QDrag
对象最好不被删除。目标部件通常会保存原始数据的引用。
实例
Dragging
开始“拖”操作,需要创建一个QDrag
对象,并调用exec()函数。在大多数应用中,最好的实现方式就是通过鼠标来进行。当鼠标被按下且光标移动到目的区域时释放就完成了拖放操作。因此,最简单实现拖放操作就是重写widget的mousePressEvent()
。
def mousePresseEvent(self, event)
if event.button() == Qt.LeftButton
drag = QDrag()
mimedata = QMimeData
mimedata.setText('aaa')#放入数据
drag.setMimeData(mimedata)
drag.exec_() #exec()函数并不会阻塞主函数
上述是最简单的’拖’操作定义方式。当然,为了避免功能冲突,也可以在mouseMoveEvent()
中进行该操作的定义。
Droping
为了使得相关的widget能够响应释放操作,需要使用setAcceptDrops(True)
并且重写相关的dragEnterEvent()
和 dropEvent()
函数。在重写dragMoveEvent()
和 dropEvent()
函数之前,必须先重写dropEnter()
函数。而dropEnter()
通常用来判断 当前widget是否接受操作带有的数据类型。而dropEvent()
通常是用来处理被释放的数据。
def dragEnterEvent(self, event)
event.acceptProposedAction()
def dropEvent(self, event)
#To Do
Reference
[1] PyQt - Drag & Drop
[2] Qt Documentation: Drag and Drop
[3] Qt Documentation: QMimeData Class
[4] PyQt4 - Drag and Drop