0

我已经实现了拖放以在列表视图中重新排序项目,并且我的所有调试输出都表明它工作正常。但是,当我再次选择一个项目时,它会恢复到视图中之前的状态,当它被取消选择时,模型中也会发生这种变化。
例子:

                       列表视图显示模型显示
                         a, b, c, da, b, c, d
拖放后 b, c, d, ab, c, d, a
单击第一项 a, c, d, ab, c, d, a
单击第二项 a, b, d, aa, c, d, a
等等

希望这是有道理的。有什么建议为什么会发生这种情况?(代码示例很困难,因为这是大型应用程序的一部分)

编辑:这是我能为代码做的最好的事情。

自定义列表视图(我有一个自定义列表视图,因为它需要在项目移动时发出信号,并且 indexMoved 似乎已损坏):

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

原来拖放工作正常。首先,一些背景。此列表视图是在大型应用程序中的多个位置使用的自定义小部件的一部分。在这个特定的地方,单击列表中的项目会导致父窗口小部件中的某些字段被启用并填充有关该项目的信息。这是根据列表视图中的当前选择完成的。其中一个字段是项目名称的行编辑。当其内容发生变化时,它会自动更新其项目的名称。

这意味着当一个项目被拖动并且选择留在后面时,行编辑的内容会发生变化,更新现在位于被拖动项目在视图中的项目,但直到稍后通过一些信号/插槽巫术才在模型中。

最终,是答案;让模型使用删除项目的行发出信号,并根据该信号而不是选择模型更新/填充字段。

于 2012-10-11T22:13:31.943 回答