QComboBox で使用する QAbstractListView を作成しようとしています。この QComboBox は、含まれているアイテムの並べ替えられたリストを維持します。私の問題を示すサンプルコードを以下にいくつか含めました。リスト内の項目を更新すると、コンボ ボックスの currentIndex が更新されず、モデルへの変更が反映されません。rowsAboutToBeInserted シグナルと rowsInserted シグナルを使用してみましたが、効果が見られません (間違っているのでしょうか?)。
私の実際の使用例はもう少し複雑ですが、この例で十分です。並べ替えられるアイテムは単なる文字列ではなく、並べ替えるにはもう少し手間がかかり、DisplayRole とは異なる ItemDataRole を持ちます。
itemsAdded と itemsRemoved は私自身の関数であり、プロキシしようとしている別のリストからの信号に接続されます。
問題を引き起こすには、'Insert "c"' ボタンを押してください。文字列はリストに正しく挿入されますが、選択は 'e' から 'd' に移動します (つまり、選択インデックスは変更されません)。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
class Model(QtCore.QAbstractListModel):
def __init__(self, *args, **kwargs):
QtCore.QAbstractListModel.__init__(self, *args, **kwargs)
self.items = []
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid() is True:
if role == QtCore.Qt.DisplayRole:
return QtCore.QVariant(self.items[index.row()])
elif role == QtCore.Qt.ItemDataRole:
return QtCore.QVariant(self.items[index.row()])
return QtCore.QVariant()
def itemsAdded(self, items):
# insert items into their sorted position
items = sorted(items)
row = 0
while row < len(self.items) and len(items) > 0:
if items[0] < self.items[row]:
self.items[row:row] = [items.pop(0)]
row += 1
row += 1
# add remaining items to end of list
if len(items) > 0:
self.items.extend(items)
def itemsRemoved(self, items):
# remove items from list
for item in items:
for row in range(0, len(self.items)):
if self.items[row] == item:
self.items.pop(row)
break
def main():
app = QtGui.QApplication([])
w = QtGui.QWidget()
w.resize(300,300)
layout = QtGui.QVBoxLayout()
model = Model()
model.itemsAdded(['a','b','d','e'])
combobox = QtGui.QComboBox()
combobox.setModel(model)
combobox.setCurrentIndex(3)
layout.addWidget(combobox)
def insertC(self):
model.itemsAdded('c')
button = QtGui.QPushButton('Insert "c"')
button.clicked.connect(insertC)
layout.addWidget(button)
w.setLayout(layout)
w.show()
app.exec_()
if __name__ == '__main__':
main()