68670


Pyqt5のQListViewを使って作ったアイテムモデルでDrag&Dropの機能を追加したいです。

txtファイルをドロップできるようにコードを書いて見たつもりなのですが、ファイルをドロップできません。

どうすればよいのでしょうか。

* * *

**表示されるGUI**

[![画像](https://i.stack.imgur.com/MgVmC.png)](https://i.stack.imgur.com/MgVmC.png)

**ソースコード**

[code]

    import sys
    from PyQt5 import QtGui,QtCore, QtWidgets
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    
    class ListView(QListView):
        def __init__(self, parent=None):
            super(ListView,self).__init__(parent)
            self.setAcceptDrops(True) 
            self.setParent(parent)
            self.win=parent
            
        def dragEnterEvent(self, e):
            print("a")
            mimeData = e.mimeData()
    
            # パスの有無で判定
            if mimeData.hasUrls():
                print("b")
                e.accept()
            else:
                print("c")
                e.ignore()
                #e.accept()
    
        def dropEvent(self, e):
            print("d")
            # ファイルから画像読込
            urls = e.mimeData().urls()
            urllength=len(urls)        
    
            for file in range(0,urllength):
                textpath=urls[file].toLocalFile()
                root, ext=os.path.splitext(textpath)
                if ext==".txt" or ext==".text":
                    print(urls[file].toLocalFile())
                else:
                    pass
    
    class TreeModel(QtCore.QAbstractItemModel):
        def __init__(self):
            QtCore.QAbstractItemModel.__init__(self)
            #self.nodes = ['node0', 'node1', 'node2', "node4", "node5"]
    
        def index(self, row, column, parent):
            return self.createIndex(row, column, nodes[row])
    
        def parent(self, index):
            return QtCore.QModelIndex()
    
        def rowCount(self, index):
            if index.internalPointer() in nodes:
                return 0
            return len(nodes)
    
        def columnCount(self, index):
            return 1
    
        def data(self, index, role):
            if role == 0: 
                return index.internalPointer()
            else:
                return None
    
        def supportedDropActions(self): 
            return QtCore.Qt.CopyAction | QtCore.Qt.MoveAction         
    
        def flags(self, index):
            if not index.isValid():
                return QtCore.Qt.ItemIsEnabled
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | \
                   QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled        
    
        def mimeTypes(self):
            return ['text/xml']
    
        def mimeData(self, indexes):
            mimedata = QtCore.QMimeData()
            mimedata.setData('text/xml', 'mimeData')
            return mimedata
    
        def dropMimeData(self, data, action, row, column, parent):
            print ('dropMimeData %s %s %s %s' % (data.data('text/xml'), action, row, parent))
            return True
    
    
    class MainForm(QWidget):
        def __init__(self, parent=None):
            super(MainForm, self).__init__(parent)
    
            self.treeModel = TreeModel()
            
            self.view = ListView()
            self.view.setModel(self.treeModel)
            self.view.activated.connect(self.viewClicked2)#ダブルクリックでの動作
            self.view.clicked.connect(self.viewClicked)
            
            self.btn=QPushButton("index0")
            self.btn.clicked.connect(self.change_index)
            
            layout = QHBoxLayout(self)
            layout.addWidget(self.view)
            layout.addWidget(self.btn)
    
            self.setLayout(layout)
    
            self.show()
            
        def viewClicked(self, indexClicked):
            print('index of proxy row', indexClicked.row())
            
        def viewClicked2(self, index):
            print(index.row())
            
        def change_index(self):
            index = self.view.model().createIndex(0, 0)
            self.view.selectionModel().select(index, QItemSelectionModel.ClearAndSelect)
    
    
    def main():
        app = QApplication(sys.argv)
        form = MainForm()
        form.show()
        app.exec_()
    
    if __name__ == '__main__':
        nodes=['node0', 'node1', 'node2', "node4", "node5"]
        main()
    
[/code]


CC BY-SA 4.0
2020-07-16T14:16:07.930
68648
2020-07-17T07:27:30.973
26529
question
python pyqt5
pyqt5のQListViewでDrag&Drop機能を追加したい


dragMoveEventを追加する必要があるみたいですね。  
<https://kiwamiden.com/drag-and-drop-files-to-qlistview>  
を参考にしました。以下は修正したコードです。

[code]

    import sys
    from PyQt5 import QtGui,QtCore, QtWidgets
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    import os
    
    class ListView(QListView):
        def __init__(self, parent=None):
            super(ListView,self).__init__(parent)
            self.setAcceptDrops(True) 
            self.setParent(parent)
            self.win=parent
            
        def dragEnterEvent(self, e):
            mimeData = e.mimeData()
    
            # パスの有無で判定
            if mimeData.hasUrls():
                e.accept()
            else:
                e.ignore()
                #e.accept()
    
        def dragMoveEvent(self, event):
            if event.mimeData().hasUrls():
                event.accept()
                 
            else:
                pass
    
        def dropEvent(self, e):
            urls = e.mimeData().urls()
            urllength=len(urls)        
    
            for file in range(0,urllength):
                textpath=urls[file].toLocalFile()
                root, ext=os.path.splitext(textpath)
                if ext==".txt" or ext==".text":
                    print(urls[file].toLocalFile())
                else:
                    pass
    
    class TreeModel(QtCore.QAbstractItemModel):
        def __init__(self):
            QtCore.QAbstractItemModel.__init__(self)
            #self.nodes = ['node0', 'node1', 'node2', "node4", "node5"]
    
        def index(self, row, column, parent):
            return self.createIndex(row, column, nodes[row])
    
        def parent(self, index):
            return QtCore.QModelIndex()
    
        def rowCount(self, index):
            if index.internalPointer() in nodes:
                return 0
            return len(nodes)
    
        def columnCount(self, index):
            return 1
    
        def data(self, index, role):
            if role == 0: 
                return index.internalPointer()
            else:
                return None
    
        def supportedDropActions(self): 
            return QtCore.Qt.CopyAction | QtCore.Qt.MoveAction         
    
        def flags(self, index):
            if not index.isValid():
                return QtCore.Qt.ItemIsEnabled
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | \
                   QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled        
    
        def mimeTypes(self):
            return ['text/xml']
    
        def mimeData(self, indexes):
            mimedata = QtCore.QMimeData()
            mimedata.setData('text/xml', 'mimeData')
            return mimedata
    
        def dropMimeData(self, data, action, row, column, parent):
            print ('dropMimeData %s %s %s %s' % (data.data('text/xml'), action, row, parent))
            return True
    
    
    class MainForm(QWidget):
        def __init__(self, parent=None):
            super(MainForm, self).__init__(parent)
    
            self.treeModel = TreeModel()
            
            self.view = ListView()
            self.view.setModel(self.treeModel)
            self.view.activated.connect(self.viewClicked2)#ダブルクリックでの動作
            self.view.clicked.connect(self.viewClicked)
            
            self.btn=QPushButton("index0")
            self.btn.clicked.connect(self.change_index)
            
            layout = QHBoxLayout(self)
            layout.addWidget(self.view)
            layout.addWidget(self.btn)
    
            self.setLayout(layout)
    
            self.show()
            
        def viewClicked(self, indexClicked):
            print('index of proxy row', indexClicked.row())
            
        def viewClicked2(self, index):
            print(index.row())
            
        def change_index(self):
            index = self.view.model().createIndex(0, 0)
            self.view.selectionModel().select(index, QItemSelectionModel.ClearAndSelect)
    
    
    def main():
        app = QApplication(sys.argv)
        form = MainForm()
        form.show()
        app.exec_()
    
    if __name__ == '__main__':
        nodes=['node0', 'node1', 'node2', "node4", "node5"]
        main()
    
[/code]


CC BY-SA 4.0
2020-07-17T07:27:30.973
68670
2020-07-17T07:27:30.973
26529
68648
answer