0

リスト ビューで項目を並べ替えるドラッグ アンド ドロップを実装しました。すべてのデバッグ出力は、これが適切に機能していることを示しています。ただし、アイテムを再度選択すると、ビューに以前あったものに戻り、選択が解除されると、この変更はモデルでも行われます。
例:

                       リスト ビュー ショー モデル ショー
                         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()))
4

1 に答える 1

0

ドラッグアンドドロップが正常に機能していたことがわかります。まず、いくつかの背景。このリストビューは、大規模なアプリケーション内のいくつかの場所で使用されるカスタムウィジェットの一部です。この特定の場所で、リスト内のアイテムをクリックすると、親ウィジェットの一部のフィールドが有効になり、そのアイテムに関する情報が入力されます。これは、リストビューでの現在の選択に基づいて行われます。フィールドの1つは、アイテム名の行編集です。内容が変更されると、アイテムの名前が自動的に更新されます。

これは、アイテムがドラッグされて選択範囲が遅れると、行編集の内容が変更され、ドラッグされたアイテムがビュー内のどこにあるかを更新しますが、信号/スロットブードゥーを介して後でモデルに存在することはありません。

最終的に、これ答えでした。アイテムがドロップされた行でシグナルを発するようにモデルを取得し、選択モデルの代わりにそれに基づいてフィールドを更新/入力します。

于 2012-10-11T22:13:31.943 に答える