スタック・オーバーフロー Asked on September 1, 2021
Pyqt5のQListViewを使って作ったアイテムモデルでDrag&Dropの機能を追加したいです。
txtファイルをドロップできるようにコードを書いて見たつもりなのですが、ファイルをドロップできません。
どうすればよいのでしょうか。
表示されるGUI
ソースコード
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()
dragMoveEventを追加する必要があるみたいですね。
https://kiwamiden.com/drag-and-drop-files-to-qlistview
を参考にしました。以下は修正したコードです。
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()
Correct answer by toma on September 1, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP