为什么单击qlistview中的项目会在拖放后将它们恢复到以前的状态



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

列表视图显示模型显示a、 b、c、d a、b、c和d拖放b、c、d、a之后点击第一项a、c、d、a、b、c、d、a单击第二项a、b、d、a、a、c、d和a等等。

希望这是有意义的。为什么会发生这种情况,有什么建议吗?(代码样本很难,因为这是大型应用程序的一部分)

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

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

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()))

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

这意味着,当一个项目被拖动而选择保留时,行编辑的内容会发生变化,更新当前位于视图中拖动项目所在位置的项目,但直到稍后通过某种信号/插槽巫毒才会在模型中更新

最终,这就是答案;让模型发出一个带有项目所在行的信号,并基于该行而不是选择模型更新/填充字段。

最新更新