拖动在“ QfileModelsystem”中不起作用

发布于 2025-01-22 04:19:55 字数 4061 浏览 0 评论 0原文

我正在尝试在qfilesystemmodel中进行拖放行为,但是由于我没有在拖放之前的经验,所以我首先在qtreeview上尝试了它。 (我附加了行为的视频)

”在此处输入图像描述“

现在我对自己想要的行为很好,然后我只是将模型更改为qfilesystemmodel ,但可悲的是它无法正常工作。因此,我尝试阅读 qfilesystemmodelmodelmodel a href =“ https://doc.qt.io/qt-5/qtreeview.html” rel =“ nofollow noreferrer”> qtreeview 从qt 拖动并删除,我最终得到了下面的代码:

我最终得到的代码:

import os
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

class MQTreeView(QTreeView):
    def __init__(self, model):
        super().__init__()
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        # self.setDragDropMode(QAbstractItemView.InternalMove)
        self.setModel(model)
        self.setDragDropMode(QAbstractItemView.DragDrop)
        self.setRootIndex(model.index(os.path.dirname(os.path.abspath("__file__"))))
        self.setDefaultDropAction(Qt.MoveAction)
        self.viewport().setAcceptDrops(True)

    def dragEnterEvent(self, event):
        m = event.mimeData()
        if m.hasUrls():
            event.accept()
            return
        event.ignore()
        # return super().dragEnterEvent(event)

    def dropEvent(self, event):
        print("[drop event] - dropped")
        if event.source():
            QTreeView.dropEvent(self, event)
        else:
            ix = self.indexAt(event.pos())
            model = self.model()

            if ix.isValid():
                if not model.isDir(ix):
                    ix = ix.parent()      # In case of folder/Dir
                pathDir = model.filePath(ix)
            else:
                # for empty drag and drop
                pathDir = model.rootPath()

            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)
                        print(f"added -> {info.fileName()}")

                    accepted = True
                if accepted:
                    event.acceptProposedAction()

        # return super().dropEvent(event)

class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        # -- right -- #
        self.model1 = QFileSystemModel()
        self.model1.setRootPath(os.path.dirname(os.path.abspath("__file__")))

        self.view1 = MQTreeView(self.model1)

        # -- left -- #
        self.model2 = QFileSystemModel()
        self.model2.setRootPath(os.path.dirname(os.path.abspath("__file__")))

        self.view2 = MQTreeView(self.model2)

        # -- layout -- #
        layout = QHBoxLayout(self)
        layout.addWidget(self.view1)
        layout.addWidget(self.view2)

app = QApplication(sys.argv)
main = AppDemo()
main.show()
app.exec_()

上面的代码仍未执行我想要的行为,但我很确定其他问题是错误的,并且没有覆盖功能(dragentereventdropevent)。我最好的猜测是,我没有正确地设置正确的方法QTREEVIEW接受下降,尽管我不确定。

我的问题:我的实施是什么问题?是我接受下降还是其他的方式?

I'm trying to make a drag and drop behavior in QFileSystemModel but because I have no experience in making a drag and drop before, I tried it first on QTreeView. (I attached the video of the behavior)

enter image description here

Now that I'm fine with the behavior I want, I then just changed the model to QFileSystemModel but sadly It's not working. So I tried to read the QFileSystemModel, QTreeView, and Drag and Drop from Qt and I ended up with the code below:

The code I ended up with:

import os
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

class MQTreeView(QTreeView):
    def __init__(self, model):
        super().__init__()
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        # self.setDragDropMode(QAbstractItemView.InternalMove)
        self.setModel(model)
        self.setDragDropMode(QAbstractItemView.DragDrop)
        self.setRootIndex(model.index(os.path.dirname(os.path.abspath("__file__"))))
        self.setDefaultDropAction(Qt.MoveAction)
        self.viewport().setAcceptDrops(True)

    def dragEnterEvent(self, event):
        m = event.mimeData()
        if m.hasUrls():
            event.accept()
            return
        event.ignore()
        # return super().dragEnterEvent(event)

    def dropEvent(self, event):
        print("[drop event] - dropped")
        if event.source():
            QTreeView.dropEvent(self, event)
        else:
            ix = self.indexAt(event.pos())
            model = self.model()

            if ix.isValid():
                if not model.isDir(ix):
                    ix = ix.parent()      # In case of folder/Dir
                pathDir = model.filePath(ix)
            else:
                # for empty drag and drop
                pathDir = model.rootPath()

            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)
                        print(f"added -> {info.fileName()}")

                    accepted = True
                if accepted:
                    event.acceptProposedAction()

        # return super().dropEvent(event)

class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        # -- right -- #
        self.model1 = QFileSystemModel()
        self.model1.setRootPath(os.path.dirname(os.path.abspath("__file__")))

        self.view1 = MQTreeView(self.model1)

        # -- left -- #
        self.model2 = QFileSystemModel()
        self.model2.setRootPath(os.path.dirname(os.path.abspath("__file__")))

        self.view2 = MQTreeView(self.model2)

        # -- layout -- #
        layout = QHBoxLayout(self)
        layout.addWidget(self.view1)
        layout.addWidget(self.view2)

app = QApplication(sys.argv)
main = AppDemo()
main.show()
app.exec_()

The code above is still not doing the behavior I want but I'm pretty sure that something else is wrong and it is not with the overridden function (dragEnterEvent and dropEvent). My best guess is that I didn't set properly the correct way QTreeView accepts the drops although I'm not really sure.

My Question: What is wrong with my Implementation? Is it the way I accept drops or it is something else?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北方的韩爷 2025-01-29 04:19:55

找到了什么问题!我没有覆盖dragMoveEvent方法。我需要覆盖dragMoveEvent以确保不会禁止阻力。

我需要在dragenterevent中接受所有拖动事件:

def dragEnterEvent(self, event):
    event.accept()

然后,我需要过滤dragmoveevent中的事件:

def dragMoveEvent(self, event):
    m = event.mimeData()
    if m.hasUrls():
        event.accept()
        print("[dropEnterEvent] - event accepted")
        return
    event.ignore()

我附加了下面的工作行为的视频和代码。

最终实现:

import os
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

class MQTreeView(QTreeView):
    def __init__(self, model, path):
        super().__init__()

        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setModel(model)
        self.setDragDropMode(QAbstractItemView.DragDrop)
        self.setRootIndex(model.index(path))
        self.setDefaultDropAction(Qt.MoveAction)
        self.viewport().setAcceptDrops(True)

    def dragEnterEvent(self, event):
        event.accept()

    def dragMoveEvent(self, event):
        m = event.mimeData()
        if m.hasUrls():
            event.accept()
            print("[dropEnterEvent] - event accepted")
            return
        event.ignore()

    def dropEvent(self, event):
        print("[drop event] - dropped")
        if event.source():
            ix = self.indexAt(event.pos())
            model = self.model()

            if ix.isValid():
                if not model.isDir(ix):
                    ix = ix.parent()
                pathDir = model.filePath(ix)
            else:
                # for empty drag and drop
                pathDir = model.rootPath()

            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)
                    destination = QDir(pathDir).filePath(info.fileName())
                    source = info.absoluteFilePath()
                    if destination == source:
                        continue  # means they are in the same folder
                    if info.isDir():
                        QDir().rename(source, destination)
                    else:
                        qfile = QFile(source)
                        if QFile(destination).exists():
                            n_info = QFileInfo(destination)
                            
                            destination = n_info.canonicalPath() + QDir.separator() + n_info.completeBaseName() + " (copy)"
                            if n_info.completeSuffix():   # for moving files without suffix
                                destination += "." + n_info.completeSuffix()

                        qfile.rename(destination)
                        print(f"added -> {info.fileName()}")  # for debugging

                    accepted = True
                if accepted:
                    event.acceptProposedAction()

class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.setAcceptDrops(True)

        cwd = "test/"
        nw = "test copy/"

        # -- right -- #
        self.model1 = QFileSystemModel()
        self.model1.setRootPath(os.path.dirname(cwd))

        self.view1 = MQTreeView(self.model1, cwd)

        # -- left -- #
        self.model2 = QFileSystemModel()
        self.model2.setRootPath(os.path.dirname(nw))

        self.view2 = MQTreeView(self.model2, nw)

        # -- layout -- #
        layout = QHBoxLayout(self)
        layout.addWidget(self.view1)
        layout.addWidget(self.view2)

app = QApplication(sys.argv)
main = AppDemo()
main.show()
app.exec_()

Found what's wrong! I didn't override the dragMoveEvent method. I need to override the dragMoveEvent to make sure that the drag will not be forbidden.

I need to accept all drag event in the dragEnterEvent:

def dragEnterEvent(self, event):
    event.accept()

Then I need to filter the events in the dragMoveEvent:

def dragMoveEvent(self, event):
    m = event.mimeData()
    if m.hasUrls():
        event.accept()
        print("[dropEnterEvent] - event accepted")
        return
    event.ignore()

I attached the video and code of the working behavior below.

enter image description here

The final implementation:

import os
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

class MQTreeView(QTreeView):
    def __init__(self, model, path):
        super().__init__()

        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setModel(model)
        self.setDragDropMode(QAbstractItemView.DragDrop)
        self.setRootIndex(model.index(path))
        self.setDefaultDropAction(Qt.MoveAction)
        self.viewport().setAcceptDrops(True)

    def dragEnterEvent(self, event):
        event.accept()

    def dragMoveEvent(self, event):
        m = event.mimeData()
        if m.hasUrls():
            event.accept()
            print("[dropEnterEvent] - event accepted")
            return
        event.ignore()

    def dropEvent(self, event):
        print("[drop event] - dropped")
        if event.source():
            ix = self.indexAt(event.pos())
            model = self.model()

            if ix.isValid():
                if not model.isDir(ix):
                    ix = ix.parent()
                pathDir = model.filePath(ix)
            else:
                # for empty drag and drop
                pathDir = model.rootPath()

            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)
                    destination = QDir(pathDir).filePath(info.fileName())
                    source = info.absoluteFilePath()
                    if destination == source:
                        continue  # means they are in the same folder
                    if info.isDir():
                        QDir().rename(source, destination)
                    else:
                        qfile = QFile(source)
                        if QFile(destination).exists():
                            n_info = QFileInfo(destination)
                            
                            destination = n_info.canonicalPath() + QDir.separator() + n_info.completeBaseName() + " (copy)"
                            if n_info.completeSuffix():   # for moving files without suffix
                                destination += "." + n_info.completeSuffix()

                        qfile.rename(destination)
                        print(f"added -> {info.fileName()}")  # for debugging

                    accepted = True
                if accepted:
                    event.acceptProposedAction()

class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.setAcceptDrops(True)

        cwd = "test/"
        nw = "test copy/"

        # -- right -- #
        self.model1 = QFileSystemModel()
        self.model1.setRootPath(os.path.dirname(cwd))

        self.view1 = MQTreeView(self.model1, cwd)

        # -- left -- #
        self.model2 = QFileSystemModel()
        self.model2.setRootPath(os.path.dirname(nw))

        self.view2 = MQTreeView(self.model2, nw)

        # -- layout -- #
        layout = QHBoxLayout(self)
        layout.addWidget(self.view1)
        layout.addWidget(self.view2)

app = QApplication(sys.argv)
main = AppDemo()
main.show()
app.exec_()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文