代码之家  ›  专栏  ›  技术社区  ›  Stefan

在PyQt5 TreeView中拖放?

  •  1
  • Stefan  · 技术社区  · 7 年前

    我正在尝试使用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_())
    

    通过上面的代码,我可以显示一个目录及其内容。我可以拖动一个项目,但拖放它不会起任何作用,也看不到拖放指示。不清楚如何

    a、 在视图中进行拖放操作,并

    b、 让它处理上下文之外的项目(例如从桌面)。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Community CDub    4 年前

    根据 docs :

    只读:布尔

    此属性保存目录模型是否允许写入文件系统

    如果此属性设置为false,则目录模型将允许 重命名、复制和删除文件和目录。

    默认情况下,此属性为true

    因此,如果要移动文件,必须将其设置为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()
                    
    
        2
  •  0
  •   MalloyDelacroix    7 年前

    在树视图子类中,必须实现 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()