2017-12-03 24 views
0

複数のファイルを選択できるようにするチェックボックスを使用するファイル選択ダイアログを作成しようとしています。また、すでに選択されている項目から開始するようにダイアログを表示したいと思います。私はこれを行うためにQTreeViewQFileSystemModelのサブクラスを使用するいくつかの例をオンラインで見つけました。ダイアログボックスが完全にレンダリングされたら、最初にチェックされるファイルパスのリストを、モデル内のQModelIndexアイテムでこれらのパスを記述する項目に接続するにはどうすればよいですか?QFileSystemModelのインデックスを使用してアイテムのサブセットを追跡するにはどうすればよいですか?

私はQModelIndex項目がチェックされ、項目がオンまたはオフされたときに、このリストを更新するdata()方法などのQFileSystemModelサブクラスのいくつかのメソッドをオーバーライドする必要があるかのリストを保つ見例。ダイアログが最初に作成されたときにいくつかの項目をチェックするのをサポートするために、私は事前にチェックされるべきファイルパスの2番目のリストを使用しようとしました。 data()メソッドのサブディレクトリQFileSystemModelでは、QModelIndex入力のファイルパスをチェックし、それが私の事前チェックリストにあれば、事前チェックリストからファイルパスを削除して、QModelIndexを他のリストに入れますチェック項目の私が抱えている問題は、モデルが作成中に何回も再生するように見えるということです。最初にdata()が呼び出され、事前にチェックされたリストからパスが削除された特定のパスのインデックスと、QModelIndexが他のリストに追加されます。ただし、一度ダイアログが完全に表示されると、そのファイルパスのQModelIndexは、事前チェックリストに入れられたインスタンスとは異なるインスタンスであるため、自分のコードではチェックする必要があることがわかりません。ここで

は、私が何を意味するか説明する例です。

import os 
import sys 

from PyQt5 import QtWidgets 

all_entries = list() 


class MyFileSystemModel(QtWidgets.QFileSystemModel): 

    def data(self, index, role): 
     if index not in all_entries: 
      all_entries.append(index) 
     return super().data(index, role) 


class Ui_Dialog(QtWidgets.QDialog): 
    def __init__(self, parent=None): 
     QtWidgets.QDialog.__init__(self, parent) 

     self.model = MyFileSystemModel() 
     self.model.setRootPath(os.path.abspath('.')) 

     self.tree = QtWidgets.QTreeView() 
     self.tree.setModel(self.model) 
     self.tree.setRootIndex(self.model.index(os.path.abspath('.'))) 

     self.llayout = QtWidgets.QVBoxLayout(parent) 
     self.but = QtWidgets.QPushButton("OK") 

     self.llayout.addWidget(self.tree) 
     self.llayout.addWidget(self.but) 

     self.setLayout(self.llayout) 

     self.but.clicked.connect(self.print_entries) 

    def print_entries(self): 
     print('*'*80) 
     for index in all_entries: 
      print(index, os.path.relpath(self.model.filePath(index), 
             os.path.abspath('.'))) 


if __name__ == "__main__": 
    app = QtWidgets.QApplication(sys.argv) 
    ui = Ui_Dialog() 
    ui.show() 

    sys.exit(app.exec_()) 

testという名前の単一のファイルとディレクトリにこのスクリプトを実行し、その後OKボタンをクリックすると、私はそう

******************************************************************************** 
<PyQt5.QtCore.QModelIndex object at 0x7ff46b991f28> test 
<PyQt5.QtCore.QModelIndex object at 0x7ff46b991f98> test 
<PyQt5.QtCore.QModelIndex object at 0x7ff46b910048> test 
<PyQt5.QtCore.QModelIndex object at 0x7ff46b9100b8> test 

を見ますall_entriesは、ファイルパスがtestの4つの異なるQModelIndexアイテムになります。私の関連するチェック可能なダイアログでは、QModelIndexのインスタンスが0x7ff46b991f28にありますが、チェックされた項目のリストには表示されますが、一度ダイアログが表示されたようですが、0x7ff46b9100b8でインスタンスを使用する必要があります。私はパスの自分のリスト内のすべてを処理することができますQModelIndexオブジェクトを使用しないでくださいが、それを使用する利点は、ファイルシステムのウォッチャーを使用してファイルシステムの変更を追跡するために私はそれを活用するファイルが変更されたかどうかを調べるためにファイルシステムを照会する必要なしに、選択されたファイルのプロパティを変更できます。

答えて

1

問題は、以下の原因がある:

  • QModelIndexはdocsによれば、モデルのアイテムを区別するために使用されるべきではない:

注:モデルインデックスが使用されるべきです直ちに廃棄してください。 は、モデルの構造を変更したりアイテムを削除したりするモデル を呼び出すと、有効なままになるようにインデックスに依存しないでください。 時間の経過とともにモデルインデックスを保持する必要がある場合は、QPersistentModelIndexを使用します。

  • ファイルがQFileSystemModelにいくつかの関連する列があり、最初の列のインデックスを保存することが適切です。

    all_entries = list() 
    
    
    class MyFileSystemModel(QtWidgets.QFileSystemModel): 
        def data(self, index, role): 
         if index.column() == 0: 
          if QPersistentModelIndex(index) not in all_entries: 
           all_entries.append(QPersistentModelIndex(index)) 
         return super().data(index, role) 
    
    [...] 
    
    def print_entries(self): 
        print('*'*80) 
        for index in all_entries: 
         ix = QModelIndex(index) # get QModelIndex from QPersistentModelIndex 
         print(index, os.path.relpath(self.model.filePath(ix),os.path.abspath('.'))) 
    
    :コードは以下である必要があり、両方の事を考えると

enter image description here

関連する問題