Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
164 views
in Technique[技术] by (71.8m points)

python - How to disable copy action when drap&drop

I'm trying to implement a QTreeView with the ability to move child items between root nodes. Here is my code. In general, it works, except for one unpleasant nuance. I can make a copy of the row item11,item12 just draging it under or above item22. enter image description here

How to prevent copy action when drag&drop?

from PyQt5.QtWidgets import QTreeView,QApplication, QWidget, QAbstractItemView, QVBoxLayout
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class QCustomItemModel(QStandardItemModel):
    def flags(self, index):
        flags = Qt.NoItemFlags

        if index.isValid():
            if index.parent() == QModelIndex():
                flags = Qt.ItemIsDropEnabled
            else:
                flags = Qt.ItemIsDragEnabled | Qt.ItemIsEnabled | Qt.ItemIsSelectable

        return flags

    def supportedDragActions( self ):
        return Qt.MoveAction

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.layout = QVBoxLayout()
        self.tree = QTreeView()

        self.tvModel = QCustomItemModel()
        self.tvModel.setHorizontalHeaderLabels(["Header1","Header2","Header3"])
        root1 = QStandardItem("root1")
        root1.appendRow([QStandardItem("item11"),QStandardItem("item12")])
        root1.appendRow([QStandardItem("item21"),QStandardItem("item22")])
        root2 = QStandardItem("root2")
        self.tvModel.appendRow(root1)
        self.tvModel.appendRow(root2)

        self.tree.setModel(self.tvModel)
        self.tree.expandAll()
        self.tree.setDragDropMode(QAbstractItemView.InternalMove)


        self.layout.addWidget(self.tree)
        self.setLayout(self.layout)
        self.setGeometry(400,300,500,300)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Copying attempt was blocked by overriding the canDropMimeData function. Here is the working code:

from PyQt5.QtWidgets import QTreeView,QApplication, QWidget, QAbstractItemView, QVBoxLayout, QGroupBox, QHBoxLayout
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class QCustomItemModel(QStandardItemModel):
    def flags(self, index):
        flags = Qt.NoItemFlags

        if index.isValid():
            if index.parent().isValid():
                flags = Qt.ItemIsDragEnabled | Qt.ItemIsEnabled | Qt.ItemIsSelectable
            else:
                flags = Qt.ItemIsDropEnabled | Qt.ItemIsEnabled

        return flags

    def canDropMimeData(self, data: 'QMimeData', action: Qt.DropAction, row: int, column: int, parent: QModelIndex) -> bool:
        if column != -1 and row != -1:
            # copy attempt
            return False

        if (not parent.parent().isValid()) and parent.column() == 0:
            return True

        return False

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.layout = QVBoxLayout()
        self.tree = QTreeView()

        self.tvModel = QCustomItemModel()
        self.tvModel.setHorizontalHeaderLabels(["Header1","Header2","Header3"])
        root1 = QStandardItem("root1")
        root1.appendRow([QStandardItem("item11"),QStandardItem("item12")])
        root1.appendRow([QStandardItem("item21"),QStandardItem("item22")])
        root2 = QStandardItem("root2")
        self.tvModel.appendRow(root1)
        self.tvModel.appendRow(root2)

        self.tree.setModel(self.tvModel)
        self.tree.expandAll()
        self.tree.setDragDropMode(QAbstractItemView.InternalMove)


        self.layout.addWidget(self.tree)
        self.setLayout(self.layout)
        self.setGeometry(400,300,500,300)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...