Предварительный выбор нескольких файлов в QFileDialog

Когда отображается диалоговое окно выбора файлов, я хочу предварительно выбрать файлы в проекте, которые уже настроены как часть этого проекта, чтобы пользователь мог выбрать новые файлы ИЛИ отменить выбор существующих (т.е. ранее выбранных) файлы.

Этот ответ предполагает возможность множественного выбора.

Для этого MRE создайте 3 файла и поместите их в подходящее ref_dir:

from PyQt5 import QtWidgets
import sys

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.button = QtWidgets.QPushButton('Test', self)
        self.button.clicked.connect(self.handle_button)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.button)

    def handle_button(self):
        options = QtWidgets.QFileDialog.Options()
        options |= QtWidgets.QFileDialog.DontUseNativeDialog
        ref_dir = 'D:\\temp'
        files_list = ['file1.txt', 'file2.txt', 'file3.txt']
        fd = QtWidgets.QFileDialog(None, 'Choose project files', ref_dir, '(*.txt)')
        fd.setFileMode(QtWidgets.QFileDialog.ExistingFiles)
        fd.setOptions(options)
        # fd.setVisible(True)
        for file in files_list:
            print(f'selecting file |{file}|')
            fd.selectFile(file)
        string_list = fd.exec()
        print(f'string list {string_list}')

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

К сожалению, несмотря на то, что ExistingFiles был выбран в качестве режима файла, я обнаружил, что только последний выбранный файл имеет выбор... но я хочу, чтобы все три были выбраны при отображении диалогового окна.

Я попытался поэкспериментировать с setVisible, чтобы увидеть, можно ли как-то добиться множественного выбора после отображения диалогового окна, но это не сработало.


person mike rodent    schedule 31.07.2021    source источник


Ответы (1)


Поскольку используется неродной файловый диалог, мы можем получить доступ к его дочерним виджетам, чтобы управлять его поведением.

Сначала я подумал об использовании модели выбора представлений элементов, но это не обновит редактирование строки, которое отвечает за проверку существования файлов и включение кнопки «ОК» в этом случае; учитывая это, очевидное решение состоит в том, чтобы вместо этого напрямую обновить строку редактирования:

    def handle_button(self):
        # ...
        existing = []
        for file in files_list:
            if fd.directory().exists(file):
                existing.append('"{}"'.format(file))
        lineEdit = fd.findChild(QtWidgets.QLineEdit, 'fileNameEdit')
        lineEdit.setText(' '.join(existing))
        if fd.exec():
            print('string list {}'.format(fd.selectedFiles()))

Единственным недостатком этого подхода является то, что сигналы fileSelected и filesSelected не отправляются.

person musicamante    schedule 31.07.2021
comment
Спасибо. Основываясь на вашей первоначальной идее, я обнаружил, что в QFileDialog есть 3 QItemSelectionModel, каждый из которых имеет rowCount из 2, даже когда вы показываете 3 файла, поэтому не уверен, что там происходит. Некоторая возня с кнопкой «Выбрать» для решения упомянутой вами проблемы может быть возможна, но это ваше решение очень умно. - person mike rodent; 31.07.2021
comment
@mikerodent вам следует искать не модель выбора, а представления элементов. В частности, QFileDialog имеет два представления, используемые для отображения файлов, QListView и QTreeView, доступные с помощью findChild вместе с именами их объектов (listView и treeView соответственно). Как только вы получите представления, вы сможете получить их модели выбора (и они синхронизированы, так что на самом деле не имеет значения, какое представление вы выберете). Поскольку вы, кажется, очень заинтересованы в QFileDialog, я предлагаю вам изучить исходный код: code.woboq.org/qt5/qtbase/src/widgets/dialogs/ - person musicamante; 01.08.2021
comment
Обратите внимание, что QFileDialog — один из немногих классов Qt, который также имеет отдельный файл пользовательского интерфейса, и вы можете найти его здесь: code.woboq.org/qt5/qtbase/src/widgets/.uic/ - person musicamante; 01.08.2021