文件对话框总是 returns 字母顺序

File dialog always returns alpha order

我正在创建一个在文件中绘制数据的应用程序。绘制的第一个文件定义了所有其他数据相对于其转换的原点。 AFAICT,无论选择顺序如何,QFileDialog 总是 returns 文件按字母顺序排列。

有没有办法return选择排序的数据?

为了说明,创建一个文件夹,其中包含名为 A、B、C 或 1、2、3 的文件。无论它们以何种方式被选择或出现在文件名行编辑中,路径列表 returned 按字母顺序排列。

import os
import sys
from PyQt5 import QtCore, QtWidgets

MYDIR = (os.environ['USERPROFILE'] + '/Desktop/numbered').replace("\", "/")

def on_button_pressed():
    paths, _ = QtWidgets.QFileDialog.getOpenFileNames(
        directory = MYDIR,
        caption='Open',
        filter=(
            'All (*.*)'
        ))

    for i, path in enumerate(paths):
        print(i, path, flush=True)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    button = QtWidgets.QPushButton("Open")
    button.pressed.connect(on_button_pressed)

    button.show()
    sys.exit(app.exec_())

编辑 @musicamate 响应的实现可能会挂起:

import os
import sys
from PyQt5 import QtCore, QtWidgets


MYDIR = (os.environ['USERPROFILE'] + '/Desktop/numbered').replace("\", "/")


class SelectionOrderFileDialog(QtWidgets.QFileDialog):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setOption(QtWidgets.QFileDialog.DontUseNativeDialog)
        self.setFileMode(QtWidgets.QFileDialog.ExistingFiles)
        self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint)

        list_view = self.findChild(QtWidgets.QListView, 'listView')
        self.selection_model = list_view.selectionModel()
        self.selection_model.selectionChanged.connect(self.check_selection)

        self.current_selection = []

    def check_selection(self):
        active_selection = []

        for index in self.selection_model.selectedRows():
            path = index.data(QtWidgets.QFileSystemModel.FilePathRole)
            active_selection.append(path)

        updated_current_selection = []

        for path in self.current_selection:
            if path in active_selection:
                updated_current_selection.append(path)
                active_selection.remove(path)

        updated_current_selection.extend(active_selection)
        self.current_selection[:] = updated_current_selection

        print(self.current_selection, flush=True)


def on_button_pressed():

    # Works fine when called as...
    # dialog = SelectionOrderFileDialog()

    # Causes hangs on Open
    dialog = SelectionOrderFileDialog(
        directory = MYDIR,
        caption='Open',
        filter=(
            'text (*.txt)'
            ';;python (*.py)'
            ';;All (*.*)'
        ))

    dialog.exec_()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    button = QtWidgets.QPushButton("Open")
    button.resize(300, 25)
    button.pressed.connect(on_button_pressed)

    button.show()
    sys.exit(app.exec_())

这种级别的控制无法通过使用静态方法实现,但可以通过使用 QFileDialog 的实例来实现。

唯一的要求是避开原生对话框,这样我们就可以访问其中一个文件视图(非原生QFileDialog有列表视图和树视图),然后连接到selectionChanged 其选择模型的信号。
然后,每次发出信号时,我们检查当前的 ordered 选择,删除已经存在的路径并通过扩展新元素来构建新列表。

    def showDialog(self):
        def checkSelection():
            selection = []
            for index in selectionModel.selectedRows():
                path = index.data(QtWidgets.QFileSystemModel.FilePathRole)
                selection.append(path)
            newOrderedPaths = []
            for path in orderedPaths:
                if path in selection:
                    newOrderedPaths.append(path)
                    selection.remove(path)
            newOrderedPaths.extend(selection)
            orderedPaths[:] = newOrderedPaths

        dialog = QtWidgets.QFileDialog(self)
        dialog.setOption(dialog.DontUseNativeDialog)
        dialog.setFileMode(dialog.ExistingFiles)
        listView = dialog.findChild(QtWidgets.QListView, 'listView')
        selectionModel = listView.selectionModel()
        selectionModel.selectionChanged.connect(checkSelection)

        orderedPaths = []

        dialog.exec_()

        print(orderedPaths)

显然,使用子类也可以做到这一点。