2017-12-03 3 views
0

확인란을 사용하여 여러 파일을 선택할 수있는 파일 선택기 대화 상자를 만들려고합니다. 또한 이미 선택된 일부 항목으로 시작하는 대화 상자가 필요합니다. 나는 이것을 수행하기 위해 QTreeViewQFileSystemModel의 하위 클래스를 사용하는 온라인 예제를 발견했다. 대화 상자가 완전히 렌더링되면 해당 경로를 설명하는 모델의 QModelIndex 항목으로 처음 검사 할 파일 경로 목록을 어떻게 연결할 수 있습니까?QFileSystemModel의 인덱스를 사용하여 항목의 하위 집합을 추적하는 방법은 무엇입니까?

예는 I은 QModelIndex 항목을 확인하고 항목을 선택하거나 선택하지 않은 경우이 목록을 업데이트 할 data() 방법과 같은 QFileSystemModel 서브 클래스의 일부 메소드를 오버라이드 (override)되어야하는 목록을 유지 보았다. 대화 상자를 처음 만들 때 일부 항목을 검사하도록 지원하기 위해 미리 검사해야하는 두 번째 파일 경로 목록을 사용하려고했습니다. 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_entriestest 파일 경로에 대해 서로 다른 네 개의 QModelIndex 항목으로 끝납니다. 관련이 많은 대화 상자에서 QModelIndex 인스턴스 (예 : 0x7ff46b991f28)가 선택 항목 목록에 표시되지만 일단 대화 상자가 표시되면이 인스턴스를 0x7ff46b9100b8에 사용해야합니다. 내 자신의 경로 목록에있는 모든 것을 처리 할 수 ​​있지만 QModelIndex 개체를 사용하지는 않지만 그 사용 이점은 QFileSystemModel이 파일 시스템 감시자를 사용하여 파일 시스템 변경 사항을 추적하고 추적 할 수 있다는 것입니다. 파일이 변경되었는지 여부를 알기 위해 파일 sytem을 질의 할 필요없이 선택된 파일의 속성.

답변

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

관련 문제