どうもです、タドスケです。
こちらの記事で QAbstractListModel を継承して独自のモデルクラスを作りましたが、
オーバーライドとかめんどいんで、てっとり早く使えそうなクラスは無いの?
と感じた方もいるのではないでしょうか。少なくとも僕は思いました。
そんなわけで調べてみたところ、文字列の1次元リスト限定で使える QStringListModel というクラスを見つけました。
この記事では、QStringListModel の使い方について、具体例とともに紹介します。
モデルオブジェクトの生成
QStringListModel の使い方は非常にシンプルです。
生成時の引数に文字列のリストを渡すだけです。
model = QStringListModel(['item1', 'item2', 'item3'])
あとはこのモデルを適当なウィジェットに渡します。
widget = QListView()
widget.setModel(model)
モデルに渡した文字列リストが QListView に反映されました。
setStringList / stringList
文字列リストは QStringListModel 生成時に渡すほか、setStringList で後から渡すこともできます。
既に文字列リストを渡していた場合は、後から渡したリストで上書きされます。
stringList で、現在渡しているリストを取得します。
model.setStringList(['item1', 'item2', 'item3'])
print(f'stringsList = {model.stringList()}')
# stringsList = ['item1', 'item2', 'item3']
おまけ:使うかもしれない機能たち
QStringListModel 固有の機能はこれだけですが、親クラス(QAbstractItemModel、QAbstractListModel)の機能も使えます。
覚えておくと便利そうな機能をいくつか紹介します。
ただ、複雑なことをやりたいのであれば、QAbstractListModel を継承したクラスを自前で用意した方が良いかもしれません。
insertRow
insertRow で、指定した row(行番号)の位置に空白行を追加します。
しかし追加するアイテムの文字列を引数で指定できないので、この後に紹介する setData を使う必要があります。
model = QStringListModel(['item1', 'item2', 'item3'])
model.insertRow(2)
↑ コードの例では、「item3」の上に空白行が追加されます。
setData
setData で指定した QModelIndex 位置にあるアイテムを編集できます。
編集位置は row で指定したいところですが、QModelIndex しか対応していないため、model.index(row) を利用して row から QModelIndex を生成しています。
model.insertRow(2)
model.setData(model.index(2), 'item4')
↑ コードの例では、挿入したアイテムのテキストを「item4」に書き換えています。
dataChanged(シグナル)
dataChanged シグナルを利用すると、アイテムが編集された時にスロット関数が呼ばれるようにできます。
def _on_data_changed(top_left: QModelIndex, bottom_right: QModelIndex) -> None:
"""データが変更された."""
print(f'dataChanged(topLeft={top_left}, bottom_right={bottom_right})')
# dataChanged(topLeft=<PySide6.QtCore.QModelIndex(2,0,0x0,QStringListModel(0x1640e345550)) at 0x000001640E1BB340>, bottom_right= ...
model.dataChanged.connect(_on_data_changed)
widget = QListView()
widget.setModel(model)
↑ コードの例では、リストのアイテムを編集すると、予め登録しておいたスロット関数 _on_data_changed が呼ばれます。
スロット関数の引数は、変更されたアイテムの位置を表します。
今回の例では一つのアイテムだけを編集しているので、 top_left だけ見れば十分です。
(複数範囲を一度に編集した場合に bottom_right が必要になるかも?)
受け取れるのはあくまで QModelIndex なので、model を参照したい場合はクラスのメンバー変数として model を保持する必要があるでしょう。
sort
sort でアイテムを指定した方法で並び替えます。
引数の1つ目は column(列番号)ですが、QStringListModel は一次元=列がないので、常に 0 を指定します。
model = QStringListModel(['item1', 'item2', 'item3'])
model.sort(0, Qt.SortOrder.DescendingOrder)
↑ コードの例では、アイテムを降順(DecendingOrder)に並び替えています。
使いにくい=使うべきではない?
これまでに紹介した通り、親クラス側の機能を使えばできることは増えます。
しかし、いずれの方法も使いにくさを感じるのではないでしょうか。
「使いにくい」ということは、「そのような使われ方を想定していない」可能性が高いです。
QStringListModel を使う場合は、文字列リストを表示する程度にとどめておくのが良さそうです。
サンプルコード
今回の内容と、ついでに QStandardItemModel を使った場合のコードを GitHub にアップしました。
以上、検証おしまい!
コメント