PyQt5使用mimeData实现拖拽事件教程示例解析下
系列文章:
pyqt5使用mimedata实现拖拽事件教程示例解析上
实现思路
1、简要介绍qmimedata
2、qmimedata的用例1:在qt实现外部文件拖拽并展示
3、qmimedata的用例2:两个qlistwidget之间的item交换
两个用例的实现效果如下:
1、简要介绍qmimedata
关于拖拽事件与qmimedata的一些关系,在第一篇文章中已经说明清楚了,这篇文章主要是往qmimedata中存放一些数据,以供拖动及放置的时候做判断(及数据通过qmimedata传递)
在第一个例子中: 由于文件的拖拽本身就存放了一些信息,因此我们并没有如第一篇文章那样创建一个qdrag,并且创建一个qmimedata
在第二个例子中: 我们此时给mimedata设置了一个text值,用于之后交换itemlist
2、qmimedata的用例1
在qt实现外部文件拖拽并展示
# -*- coding: utf-8 -*- import sys from pyqt5.qtwidgets import qapplication, qmainwindow, qtextedit from pyqt5.qtcore import qiodevice, qfile class complexdrag(qmainwindow): def __init__(self): super(complexdrag, self).__init__() self.setacceptdrops(true) self.texteditor = none self.initui() def initui(self): self.texteditor = qtextedit() self.setcentralwidget(self.texteditor) self.texteditor.setacceptdrops(false) self.setacceptdrops(true) self.setwindowtitle("拖拽") def dragenterevent(self, event): if event.mimedata().hasformat("text/uri-list"): # 关于这个函数和accept的区别在下面会展示 event.acceptproposedaction() def dropevent(self, event): urls = event.mimedata().urls() if urls == "": return filename = urls.pop().tolocalfile() if filename == "": return if self.readfile(filename): self.setwindowtitle("drag file success") def readfile(self, filename): r = false file = qfile(filename) content = "" if file.open(qiodevice.readonly): content = file.readall() r = true self.texteditor.settext(str(content, "utf-8")) return r if __name__ == '__main__': app = qapplication(sys.argv) ex = complexdrag() ex.show() app.exec_()
上述代码可以将外部的文件拖进来并进行展示,其中有几个要点要注意一下:
1、我们并没有创建qdrag事件,因为拖拽的起始并非在该窗口及窗口内的widget中,而是从外部直接拖拽进来,这类事件本身已经有qdrag了
2、我们利用qmimedata中携带的信息判断进入的拖拽事件是否为我们所需要的,即event.mimedata().hasformat(“text/uri-list”), 关于里面的类型,可以自行查找该网站media types
3、上面我们没有使用 event.accept 而是使用 acceptproposedaction 的原因如下图
4、拖放结束后,我们将文件读取进来并进行展示
3、qmimedata的用例2
两个qlistwidget之间的item交换
# -*- coding: utf-8 -*- import sys from threading import event from pyqt5.qtgui import qdrag, qpixmap from pyqt5.qtwidgets import qapplication, qhboxlayout, qlistwidget, qdialog from pyqt5.qtcore import qmimedata, qt class mainwindow(qdialog): def __init__(self): super(mainwindow, self).__init__() self.projecta = complexdrag(self) self.projectb = complexdrag(self) self.projecta.additem("giosue carducci") self.projecta.additem("eyvind johnson") self.projecta.additem("sally prudhomme") self.projecta.additem("henryk sienkiewicz") self.projecta.additem("carl spitteler") self.projecta.additem("rabindranath tagore") self.projecta.additem("kawabata yasunari") self.projectb.additem("rudolf eucken") self.projectb.additem("anatole france") self.projectb.additem("rudyard kipling") self.projectb.additem("thomas mann") self.projectb.additem("eugene o'neill") self.projectb.additem("sigrid undset") lay = qhboxlayout() lay.addwidget(self.projecta) lay.addwidget(self.projectb) self.setlayout(lay) class complexdrag(qlistwidget): ondropevent = event() def __init__(self, parent=none): super(complexdrag, self).__init__(parent) self.setacceptdrops(true) self.startpos = none def removesel(self): listitems = self.selecteditems() if not listitems: return for item in listitems: self.takeitem(self.row(item)) def mousepressevent(self, event): if event.button() == qt.leftbutton: self.startpos = event.pos() super(complexdrag, self).mousepressevent(event) def mousemoveevent(self, event): distance = (event.pos() - self.startpos).manhattanlength() if distance >= qapplication.startdragdistance(): item = self.currentitem() if item: mimedata = qmimedata() mimedata.settext(item.text()) drag = qdrag(self) drag.setmimedata(mimedata) pixmap = qpixmap("computer.svg").scaled(20, 20, qt.keepaspectratio) drag.setpixmap(pixmap) self.removeitemwidget(item) if drag.exec(qt.moveaction) == qt.moveaction: self.removesel() super(complexdrag, self).mousemoveevent(event) def dragmoveevent(self, event): source = event.source() if source and source != self: event.setdropaction(qt.moveaction) def dragenterevent(self, event): source = event.source() if source and source != self: event.setdropaction(qt.moveaction) event.accept() def dropevent(self, event): source = event.source() if source and source != self: self.additem(event.mimedata().text()) event.setdropaction(qt.moveaction) if __name__ == '__main__': app = qapplication(sys.argv) ex = mainwindow() ex.show() app.exec_()
简要说明一下上面的实现过程:
1、我们在一个qwidget里面放置了两个qlistwidget,并实现qlistwidget之间item的交换
2、qlistwidget中在mousemoveevent中创建了qdrag,并且我们创建一个qmimedata, 并在其存储当前选中item的text ,此处我们还设置了拖拽时候的图标样式(上面gif的是没有调整过大小的,实际效果可以把代码拿去自己运行一下)
3、在dragmoveevent中判断是否为同源事件,非同源则将当前的拖拽设置为qt.moveaction
4、在dragenterevent中接收符合条件的拖拽事件
5、在dropevent中,从qmimedata中获取最初设置的text值,并添加到当前的qlistwidget,要注意的是,这里的self并非最初qdra*生信号的self,两个self在这里其实代表的分别是两个窗口
6、在上一篇文章中 说过,exec方法是阻塞方法 ,因此在整个拖拽事件运行完之后,又会回到下面这段代码中,把后面的方法执行完,此时我们删去自身被拖动的item
if drag.exec(qt.moveaction) == qt.moveaction: self.removesel()
以上就是pyqt5使用mimedata实现拖拽事件教程示例解析下的详细内容,更多关于pyqt5拖拽事件mimedata使用的资料请关注其它相关文章!