如何解决对模型进行排序后更新 QListView 选择
在对模型进行排序并调用 layoutChanged.emit() 之后,我的 QListView 项目显示顺序得到更新,但选择保持在同一行(由于排序,它现在包含另一个项目)。
如何更新选择以遵循排序?
class Window(QMainWindow,Ui_MainWindow):
def __init__(self,parent=None):
super().__init__(parent)
self.setupUi(self)
self.sequenceModel = SequenceModel()
def editSequence(self):
indexes = self.listView_sch_sequences.selectedIndexes()
if indexes:
# Indexes is a list of a single item in single-select mode.
index = indexes[0]
sequence = self.sequenceModel.sequences[index.row()]
sequence.name = self.lineEdit_sch_seq_name.text()
sequence.speed = self.spinBox_sch_speed.value()
sequence.order = self.spinBox_order.value()
self.sequenceModel.sequences.sort(key=lambda x: x.order,reverse=True)
self.sequenceModel.layoutChanged.emit()
class SequenceModel(QtCore.QAbstractListModel):
def __init__(self,*args,todos=None,**kwargs):
super(SequenceModel,self).__init__(*args,**kwargs)
self.NameRole = Qt.UserRole + 1
self.DataRole = Qt.UserRole + 2
self.sequences = []
def data(self,index,role):
row = index.row()
if role == Qt.DisplayRole:
text = self.sequences[row].name
return text
if role == self.DataRole:
sequence = self.sequences[row]
return sequence
def rowCount(self,index):
return len(self.sequences)
class Sequence:
def __init__(self,name: str,speed: int):
self.name = name
self.speed = speed
self.order = 0
解决方法
改变内部数据结构是不够的:Qt 模型索引(和选择)使用基于行、列和父级的引用来访问内部数据。
如果索引引用第 0 行并且您的数据结构没有跟上索引引用,则该索引将始终引用数据的第一个索引。
选择索引遵循相同的模式,这意味着模型更新持久索引引用很重要。每当您更改内部布局时,必须保持对该布局的索引引用,因此如果您需要对当前模型进行排序,则必须调用 changePersistentIndexList()
。
最好在模型类中完成所有这些操作,而不是从外部进行。
这是一个可能的实现:
class SequenceModel(QtCore.QAbstractListModel):
# ...
def sortByOrder(self):
oldIndexes = [self.index(i,0) for i in range(len(self.sequences))]
newIndexes = sorted(
oldIndexes,key=lambda i: i.data(self.DataRole).order,reverse=True
)
self.changePersistentIndexList(oldIndexes,newIndexes)
self.layoutChanged.emit()
然后,只需在设置新序列实例属性后立即从 self.sequenceModel.sortByOrder()
调用 editSequence
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。