【问题标题】:Drag and drop within PyQt5 TreeView?在 PyQt5 TreeView 中拖放?
【发布时间】:2018-06-15 17:52:14
【问题描述】:

我正在尝试使用 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.让它与该上下文之外的项目一起工作(例如来自桌面)。

【问题讨论】:

    标签: python drag-and-drop pyqt pyqt5 qtreeview


    【解决方案1】:

    根据docs

    只读:布尔

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

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

    该属性默认为真

    因此,如果您希望能够移动文件,则必须将其设置为 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()
                    
    

    【讨论】:

    • 这对我有用,感谢您的帮助 eyllanesc!
    【解决方案2】:

    在您的树视图子类中,您必须实现 dragEnterEvent dragMoveEventdropEvent

    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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      相关资源
      最近更新 更多