2017-11-13 22 views
1

PySideでは、手作業で行を選択して選択することなく数百のツリービュー項目を選択する方法はありますか?このメソッドの問題は、新しい行が選択されるたびにUI更新が行われ、メソッドが終了するまでアプリケーションがフリーズすることになります。私が選択したいすべての行のリストを選択モデルに渡すことができる方法はありますか?QTreeViewのインデックスリストから選択項目を設定する

私のtreeviewはhundresの行と4つの列を持っていますが、ツリービューはセルではなく行全体を選択するように設定されています。

model = self.uiFilesList.model() 
rows = self.selectedFileItems.selectedRows() 
self.uiFilesList.selectionModel().clear() 

これはうまくいくと思いますが、そうではありません。

selection = self.uiFilesList.selectionModel().selection() 
self.uiFilesList.selectionModel().clear() 
mode = QtGui.QItemSelectionModel.Select | QtGui.QItemSelectionModel.Rows 
self.uiFilesList.selectionModel().select(selection, mode) 

ここでは、モードでデータを更新した後に選択が更新されないサンプルプロジェクトを示します。表示されたデータを更新するためには、右クリックして年齢やジャージー番号を変更するときにリストを再投入する必要があります。しかし、私はリストを更新する前に選択範囲を保存しようとします。その後、リストが再生成された後に復元しようとしますが、動作するようには見えません。

import sys, os, random 
from PySide import QtGui, QtCore 

class Person(object): 

    def __init__(self, name, age, hair, jersey): 
     self.name = name 
     self.age = age 
     self.hair = hair 
     self.jersey = jersey 


class MainWindow(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 
     self.resize(500, 320) 

     self.people = [ 
      Person('Kevin', 10, 'Brown', 20), 
      Person('Marsha', 32, 'Blonde', 00), 
      Person('Leslie', 27, 'Black', 15), 
      Person('Tim', 53, 'Red', 37), 
      Person('Marie', 65, 'Brown', 101), 
      Person('Bella', 8, 'Blonde', 1) 
     ] 

     self.treeview = QtGui.QTreeView() 
     self.treeview.setAlternatingRowColors(True) 
     self.treeview.setModel(QtGui.QStandardItemModel()) 
     self.treeview.setSortingEnabled(True) 
     self.treeview.setRootIsDecorated(False) 
     self.treeview.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) 
     self.treeview.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) 
     self.treeview.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) 
     self.treeview.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 
     self.treeview.customContextMenuRequested.connect(self.open_menu) 
     self.selectedItems = self.treeview.selectionModel() 
     self.setCentralWidget(self.treeview) 
     self.populate_list() 

     # actions 
     self.actRandomizeAges = QtGui.QAction('Randomize Ages', self) 
     self.actRandomizeJerseys = QtGui.QAction('Randomize Jersey Numbers', self) 

     # menu 
     self.cmenu = QtGui.QMenu() 
     self.cmenu.addAction(self.actRandomizeAges) 
     self.cmenu.addAction(self.actRandomizeJerseys) 

     # connections 
     self.actRandomizeAges.triggered.connect(self.randomize_ages) 
     self.actRandomizeJerseys.triggered.connect(self.randomize_jerseys) 

    def open_menu(self, position): 
     self.cmenu.exec_(self.treeview.viewport().mapToGlobal(position)) 


    def randomize_ages(self): 
     rows = self.selectedItems.selectedRows() 
     for i, item in enumerate(rows): 
      obj = item.data(role=QtCore.Qt.UserRole) 
      obj.age = random.randint(0, 70) 
     self.populate_list() 


    def randomize_jerseys(self): 
     rows = self.selectedItems.selectedRows() 
     for i, item in enumerate(rows): 
      obj = item.data(role=QtCore.Qt.UserRole) 
      obj.jersey = random.randint(1, 100) 
     self.populate_list() 


    def populate_list(self): 
     selection = self.treeview.selectionModel().selection() 
     flags = QtGui.QItemSelectionModel.Select 
     self.treeview.selectionModel().clear() 

     model = self.treeview.model() 
     model.clear() 
     model.setHorizontalHeaderLabels(['Name','Age','Hair', 'Jersey']) 

     for p in self.people: 
      # column 1 
      col1 = QtGui.QStandardItem() 
      col1.setData(p.name, role=QtCore.Qt.DisplayRole) 
      col1.setData(p, role=QtCore.Qt.UserRole) 
      # column 2 
      col2 = QtGui.QStandardItem() 
      col2.setData(p.age, role=QtCore.Qt.DisplayRole) 
      if p.age > 30: 
       col2.setData(QtGui.QBrush(QtGui.QColor(255,0,0,255)), role=QtCore.Qt.ForegroundRole) 
      # column 3 
      col3 = QtGui.QStandardItem() 
      col3.setData(p.hair, role=QtCore.Qt.DisplayRole) 
      # column 4 
      col4 = QtGui.QStandardItem() 
      col4.setData(p.jersey, role=QtCore.Qt.DisplayRole) 
      if p.jersey > 30: 
       col4.setData(QtGui.QBrush(QtGui.QColor(0,0,255,255)), role=QtCore.Qt.ForegroundRole) 

      model.appendRow([col1, col2, col3, col4]) 

     self.treeview.selectionModel().select(selection, flags) 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    ex = MainWindow() 
    ex.show() 
    sys.exit(app.exec_()) 

答えて

2

selection-flagsが正しく使用されていないため、この例は機能しません。 QItemSelectionModel.Selectだけを使用すると、正しく動作し(行全体が選択されます)。

インデックスのリストから選択範囲を設定するには、連続した範囲をカバーする一連のQItemSelectionオブジェクトを作成し、すべてを1つの選択肢にマージします。ここで

は何をする方法を示してデモスクリプトである:

import sys 
from PySide import QtCore, QtGui 

class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     self.button = QtGui.QPushButton('Select') 
     self.button.clicked.connect(self.handleButton) 
     self.tree = QtGui.QTreeView() 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.tree) 
     layout.addWidget(self.button) 
     columns = 'One Two Three Four'.split() 
     mod = QtGui.QStandardItemModel(self) 
     mod.setHorizontalHeaderLabels(columns) 
     for row in range(1000): 
      mod.appendRow((
       QtGui.QStandardItem('A%s' % row), 
       QtGui.QStandardItem('B%s' % row), 
       QtGui.QStandardItem('C%s' % row), 
       QtGui.QStandardItem('D%s' % row), 
       )) 
     self.tree.setModel(mod) 
     self.tree.setSelectionMode(
      QtGui.QAbstractItemView.ExtendedSelection) 

    def handleButton(self): 
     mod = self.tree.model() 
     columns = mod.columnCount() - 1 
     flags = QtGui.QItemSelectionModel.Select 
     selection = QtGui.QItemSelection() 
     for start, end in ((2, 15), (25, 260), (500, 996)): 
      start, end = mod.index(start, 0), mod.index(end, columns) 
      if selection.indexes(): 
       selection.merge(QtGui.QItemSelection(start, end), flags) 
      else: 
       selection.select(start, end) 
     self.tree.selectionModel().clear() 
     self.tree.selectionModel().select(selection, flags) 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = Window() 
    window.setGeometry(700, 50, 500, 600) 
    window.show() 
    sys.exit(app.exec_()) 

UPDATE

あなたpopulate_list方法は、モデル、意志をクリアしますので、あなたの質問の例では動作しません。選択範囲内のすべてのインデックスを無効にします。したがって、現在の選択範囲を(モデルインデックスではなく)行番号のリストとして保存する方法が必要です。これは、選択を再作成するために私が上記で与えたメソッドに供給することができます。次のようにあなたがあなたの例を更新した場合、予想通り、それが動作するはず

def save_selection(self): 
    selection = self.treeview.selectionModel().selectedRows() 
    blocks = [] 
    for count, index in enumerate(sorted(selection)): 
     row = index.row() 
     if count > 0 and row == block[1] + 1: 
      block[1] = row 
     else: 
      block = [row, row] 
      blocks.append(block) 
    return blocks 

def create_selection(self, blocks): 
    mod = self.treeview.model() 
    columns = mod.columnCount() - 1 
    flags = QtGui.QItemSelectionModel.Select 
    selection = QtGui.QItemSelection() 
    for start, end in blocks: 
     start, end = mod.index(start, 0), mod.index(end, columns) 
     if selection.indexes(): 
      selection.merge(QtGui.QItemSelection(start, end), flags) 
     else: 
      selection.select(start, end) 
    self.treeview.selectionModel().clear() 
    self.treeview.selectionModel().select(selection, flags) 

def populate_list(self): 
    selection = self.save_selection() 

    ... # re-populate model 

    self.create_selection(selection) 
+0

私はあなたが私のコード例で言ってみました、それは私が私の例で私の元の質問を更新しました – JokerMartini

+0

を動作しませんでしたここで選択は更新されません。 – JokerMartini

+0

@ JokerMartini。私は問題を解決するいくつかの追加コードを追加しました。 – ekhumoro

関連する問題