PyQt5 removeRowsを使ってQTreeViewの行を削除する
2020/02/26 categories:PyQt5| tags:Python|PyQt5|QTreeView|
QTreeViewのremoveRowsメソッドを使って行の削除を試してみました。
removeRowsメソッド
removeRowsメソッドの処理はbeginRemoveRowsを発行してからアイテムを削除した後にendRemoveRowsを発行するだけです。
def removeRows(self, row, count, parent=QtCore.QModelIndex()):
if not parent.isValid():
parent_item = self.root_item
else:
parent_item = parent.internalPointer()
self.beginRemoveRows(parent, row, row + count - 1)
parent_item.removeChildren(row, row + count)
self.endRemoveRows()
選択したインデックスの削除
QMainwindowなどから選択したアイテムを削除する場合は少し処理が面倒になります。まずは選択したアイテムから行番号の重複がないリストを作成します。
def unique_row_indexes(self, indexes):
indexes2 = []
for index in indexes:
if not index.row() in set( i.row() for i in indexes2 if i.parent() == index.parent() ):
indexes2.append(index)
return indexes2
selected = self.unique_row_indexes(self.ui.treeView.selectedIndexes())
次に、先ほど作成したリストから、階層が最も浅いインデックスだけを再帰的に抽出します。例えば、Aの子がBでAとBが選択されていた場合はAのみを抽出します。
def is_selected_parent(index, selected):
if index == QtCore.QModelIndex():
return False
parent = index.parent()
if parent in selected:
return True
return is_selected_parent(parent, selected)
indexes = [ index for index in selected if not is_selected_parent(index, selected) ]
その後、アイテムを親ごとのリストに分けます。
parent_splited = {}
for index in indexes:
if not index.parent() in parent_splited:
parent_splited[index.parent()] = []
parent_splited[index.parent()].append(index)
そして最後に、親ごとに分けられたリストの最後からアイテムを削除していきます。
for key in parent_splited:
_sorted = sorted( parent_splited[key], key=lambda t:t.row() )[::-1]
for index in _sorted:
self.model.removeRows(index.row(), 1, index.parent())
以上をまとめて、下記のようなメソッドにしました。
def delete_item(self):
def is_selected_parent(index, selected):
if index == QtCore.QModelIndex():
return False
parent = index.parent()
if parent in selected:
return True
return is_selected_parent(parent, selected)
selected = self.unique_row_indexes(self.ui.treeView.selectedIndexes())
indexes = [ index for index in selected if not is_selected_parent(index, selected) ]
parent_splited = {}
for index in indexes:
if not index.parent() in parent_splited:
parent_splited[index.parent()] = []
parent_splited[index.parent()].append(index)
for key in parent_splited:
_sorted = sorted( parent_splited[key], key=lambda t:t.row() )[::-1]
for index in _sorted:
self.model.removeRows(index.row(), 1, index.parent())