リスト ビューで項目を並べ替えるドラッグ アンド ドロップを実装しました。すべてのデバッグ出力は、これが適切に機能していることを示しています。ただし、アイテムを再度選択すると、ビューに以前あったものに戻り、選択が解除されると、この変更はモデルでも行われます。
例:
リスト ビュー ショー モデル ショー a、b、c、da、b、c、d ドラッグ アンド ドロップ後、b、c、d、ab、c、d、a 最初の項目 a、c、d、ab、c、d、a をクリック 2 番目の項目 a、b、d、aa、c、d、a をクリック 等
うまくいけば、これは理にかなっています。なぜこれが起こっているのでしょうか?(これは大規模なアプリケーションの一部であるため、コード サンプルは困難です)
編集:これは、コードに対してできる最善のことです。
カスタム リスト ビュー (項目が移動したときにシグナルを発する必要があり、indexesMoved が壊れているように見えるため、カスタム リスト ビューがあります):
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import traceback
class ListOrderView(QListView):
itemMoved = pyqtSignal(int, int, QStandardItem) # Old index, new index, item
def __init__(self, parent=None):
try:
super(ListOrderView, self).__init__(parent)
self.setAcceptDrops(True)
self.setDragEnabled(True)
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setDefaultDropAction(Qt.MoveAction)
self.dragItem = None
self.dragRow = None
except:
Trace2.WriteLine(str(traceback.format_exc())) #writes stuff to a log file
def dropEvent(self, event):
try:
super(ListOrderView, self).dropEvent(event)
self.itemMoved.emit(self.dragRow, self.row(self.dragItem), self.dragItem)
self.dragItem = None
except:
Trace2.WriteLine(str(traceback.format_exc()))
def startDrag(self, supportedActions):
try:
self.dragItem = self.currentItem()
self.dragRow = self.row(self.dragItem)
super(ListOrderView, self).startDrag(Qt.MoveAction)
except:
Trace2.WriteLine(str(traceback.format_exc()))
def currentItem(self):
index = self.currentIndex()
item = self.model().itemFromIndex(index)
return item
def row(self, item):
index = self.selectedIndexes()[0]
row = index.row()
return row
それを使用するGUI(qtデザイナーで作成されたカスタムリストビューを備えた単なるフォーム):
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from FormsUI.ListOrderControlUI import Ui_ListOrderControl
import traceback
class ListOrderControl(QWidget, Ui_ListOrderControl):
def __init__(self, parent=None):
super(ListOrderControl, self).__init__(parent)
self.setupUi(self)
self.model = QStandardItemModel()
self.model.setSupportedDragActions(Qt.MoveAction)
self.listOrderView.setModel(self.model) #the custom list view
self.model.dataChanged.connect(self.onDataChanged)
def addItem(self, string, select=False):
item = QStandardItem(string)
item.setDropEnabled(False)
self.model.invisibleRootItem().appendRow(item)
if select:
self.listOrderView.selectionModel().setCurrentIndex(self.model.indexFromItem(item), QItemSelectionModel.ClearAndSelect)
def setNewItem(self, row, item):
self.model.setItem(row, item)
def removeRows(self, row, count):
self.model.removeRows(row, count)
# This is here because items are becoming drop enabled when they become unselected.
# No idea why.
def onDataChanged(self, topLeft, bottomRight):
try:
i = topLeft.row()
while i <= bottomRight.row():
item = self.model.item(i)
item.setDropEnabled(False)
i+=1
except:
Trace2.WriteLine(str(traceback.format_exc()))
def printModelContents(self):
Trace2.WriteLine("[LISTCONTROL] item order is:")
for i in range(self.model.rowCount()):
Trace2.WriteLine("\t" + str(self.model.item(i).data(Qt.DisplayRole).toString()) + " dropEnabled = " + str(self.model.item(i).isDropEnabled()))