在 PyQt5 TreeView 中拖放?
Drag and drop within PyQt5 TreeView?
我正在尝试使用 PyQt5 实现文件目录。我想在此树中加入拖放功能以支持内部 和外部 文件(即,如果我的桌面上有一些文件,我希望能够删除它们放入我的 PyQt 视图中的文件夹中)。这是我目前拥有的:
from PyQt5.QtWidgets import QTreeView,QFileSystemModel,QApplication,
QMenu, QAbstractItemView
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from src import config
class Tree(QTreeView):
def __init__(self):
QTreeView.__init__(self)
cfg = config.get()
model = QFileSystemModel()
model.setRootPath("/Users/")
self.setModel(model)
self.setRootIndex(model.index("/Users/"))
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.open_menu)
self.setSelectionMode(self.SingleSelection)
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setDragEnabled(True)
self.setAcceptDrops(True)
self.setDropIndicatorShown(True)
def open_menu(self):
menu = QMenu()
menu.addAction("Create new folder")
menu.exec_(QCursor.pos())
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
通过上面的代码,我可以显示目录及其内容。我可以拖动一个项目,但放下它什么都不做,也看不到放置指示。目前还不清楚如何
一个。在视图中进行拖放操作
b。让它与该上下文之外的项目一起工作(例如从桌面)。
根据 docs:
readOnly : bool
This property holds whether the directory model allows writing to the file system
If this property is set to false, the directory model will allow
renaming, copying and deleting of files and directories.
This property is true by default
因此,如果您希望能够移动文件,则必须将其设置为 False:
model.setReadOnly(False)
您必须覆盖 dragEnterEvent
方法,如果存在相对于本地资源的 QUrl
您必须接受它。
然后你必须覆盖dropEvent
方法,如果事件没有来源那么它意味着它来自外部来源作为本地文件,然后实现一个逻辑来移动文件或目录检查文件或目录是否存在或不创建新路径。
class Tree(QTreeView):
def __init__(self):
QTreeView.__init__(self)
model = QFileSystemModel()
model.setRootPath(QDir.currentPath())
self.setModel(model)
self.setRootIndex(model.index(QDir.currentPath()))
model.setReadOnly(False)
self.setSelectionMode(self.SingleSelection)
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setDragEnabled(True)
self.setAcceptDrops(True)
self.setDropIndicatorShown(True)
def dragEnterEvent(self, event):
m = event.mimeData()
if m.hasUrls():
for url in m.urls():
if url.isLocalFile():
event.accept()
return
event.ignore()
def dropEvent(self, event):
if event.source():
QTreeView.dropEvent(self, event)
else:
ix = self.indexAt(event.pos())
if not self.model().isDir(ix):
ix = ix.parent()
pathDir = self.model().filePath(ix)
m = event.mimeData()
if m.hasUrls():
urlLocals = [url for url in m.urls() if url.isLocalFile()]
accepted = False
for urlLocal in urlLocals:
path = urlLocal.toLocalFile()
info = QFileInfo(path)
n_path = QDir(pathDir).filePath(info.fileName())
o_path = info.absoluteFilePath()
if n_path == o_path:
continue
if info.isDir():
QDir().rename(o_path, n_path)
else:
qfile = QFile(o_path)
if QFile(n_path).exists():
n_path += "(copy)"
qfile.rename(n_path)
accepted = True
if accepted:
event.acceptProposedAction()
在您的树视图子类中,您必须实现 dragEnterEvent
dragMoveEvent
和 dropEvent
.
class Tree(QTreeView):
def __init__(self):
QTreeView.__init__(self)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls:
event.accept()
else:
event.ignore()
def dragMoveEvent(self, event):
if event.mimeData().hasUrls:
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
else:
event.ignore()
def dropEvent(self, event):
if event.mimeData().hasUrls:
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
# to get a list of files:
drop_list = []
for url in event.mimeData().urls():
drop_list.append(str(url.toLocalFile()))
# handle the list here
else:
event.ignore()
我正在尝试使用 PyQt5 实现文件目录。我想在此树中加入拖放功能以支持内部 和外部 文件(即,如果我的桌面上有一些文件,我希望能够删除它们放入我的 PyQt 视图中的文件夹中)。这是我目前拥有的:
from PyQt5.QtWidgets import QTreeView,QFileSystemModel,QApplication,
QMenu, QAbstractItemView
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from src import config
class Tree(QTreeView):
def __init__(self):
QTreeView.__init__(self)
cfg = config.get()
model = QFileSystemModel()
model.setRootPath("/Users/")
self.setModel(model)
self.setRootIndex(model.index("/Users/"))
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.open_menu)
self.setSelectionMode(self.SingleSelection)
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setDragEnabled(True)
self.setAcceptDrops(True)
self.setDropIndicatorShown(True)
def open_menu(self):
menu = QMenu()
menu.addAction("Create new folder")
menu.exec_(QCursor.pos())
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
通过上面的代码,我可以显示目录及其内容。我可以拖动一个项目,但放下它什么都不做,也看不到放置指示。目前还不清楚如何
一个。在视图中进行拖放操作
b。让它与该上下文之外的项目一起工作(例如从桌面)。
根据 docs:
readOnly : bool
This property holds whether the directory model allows writing to the file system
If this property is set to false, the directory model will allow renaming, copying and deleting of files and directories.
This property is true by default
因此,如果您希望能够移动文件,则必须将其设置为 False:
model.setReadOnly(False)
您必须覆盖 dragEnterEvent
方法,如果存在相对于本地资源的 QUrl
您必须接受它。
然后你必须覆盖dropEvent
方法,如果事件没有来源那么它意味着它来自外部来源作为本地文件,然后实现一个逻辑来移动文件或目录检查文件或目录是否存在或不创建新路径。
class Tree(QTreeView):
def __init__(self):
QTreeView.__init__(self)
model = QFileSystemModel()
model.setRootPath(QDir.currentPath())
self.setModel(model)
self.setRootIndex(model.index(QDir.currentPath()))
model.setReadOnly(False)
self.setSelectionMode(self.SingleSelection)
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setDragEnabled(True)
self.setAcceptDrops(True)
self.setDropIndicatorShown(True)
def dragEnterEvent(self, event):
m = event.mimeData()
if m.hasUrls():
for url in m.urls():
if url.isLocalFile():
event.accept()
return
event.ignore()
def dropEvent(self, event):
if event.source():
QTreeView.dropEvent(self, event)
else:
ix = self.indexAt(event.pos())
if not self.model().isDir(ix):
ix = ix.parent()
pathDir = self.model().filePath(ix)
m = event.mimeData()
if m.hasUrls():
urlLocals = [url for url in m.urls() if url.isLocalFile()]
accepted = False
for urlLocal in urlLocals:
path = urlLocal.toLocalFile()
info = QFileInfo(path)
n_path = QDir(pathDir).filePath(info.fileName())
o_path = info.absoluteFilePath()
if n_path == o_path:
continue
if info.isDir():
QDir().rename(o_path, n_path)
else:
qfile = QFile(o_path)
if QFile(n_path).exists():
n_path += "(copy)"
qfile.rename(n_path)
accepted = True
if accepted:
event.acceptProposedAction()
在您的树视图子类中,您必须实现 dragEnterEvent
dragMoveEvent
和 dropEvent
.
class Tree(QTreeView):
def __init__(self):
QTreeView.__init__(self)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls:
event.accept()
else:
event.ignore()
def dragMoveEvent(self, event):
if event.mimeData().hasUrls:
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
else:
event.ignore()
def dropEvent(self, event):
if event.mimeData().hasUrls:
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
# to get a list of files:
drop_list = []
for url in event.mimeData().urls():
drop_list.append(str(url.toLocalFile()))
# handle the list here
else:
event.ignore()