简体   繁体   English

在 QFileDialog pyqt5 中选择文件或文件夹

[英]Select a file or a folder in QFileDialog pyqt5

My scrip ist currently using QtWidgets.QFileDialog.getOpenFileNames() to let the user select files within Windows explorer.我的脚本目前使用 QtWidgets.QFileDialog.getOpenFileNames() 让用户在 Windows 资源管理器中选择文件。 Now I´m wondering if there is a way to let them select also folders, not just files.现在我想知道是否有办法让他们也选择文件夹,而不仅仅是文件。 There are some similar posts, but none of them provides a working solution.有一些类似的帖子,但没有一个提供有效的解决方案。 I really dont want to use the QFileDialog file explorer to get around this.我真的不想使用 QFileDialog 文件资源管理器来解决这个问题。

QFileDialog doesn't allow that natively. QFileDialog 本身不允许这样做。 The only solution is to create your own instance, do some small "patching".唯一的解决方案是创建自己的实例,做一些小的“修补”。

Note that in order to achieve this, you cannot use the native dialogs of your OS, as Qt has almost no control over them;请注意,为了实现这一点,您不能使用操作系统的本机对话框,因为 Qt 几乎无法控制它们; that's the reason of the dialog.DontUseNativeDialog flag, which is mandatory.这就是dialog.DontUseNativeDialog标志的原因,这是强制性的。

The following code works as much as static methods do, and returns the selected items (or none, if the dialog is cancelled).下面的代码和静态方法一样工作,并返回选定的项目(或不返回,如果对话框被取消)。

def getOpenFilesAndDirs(parent=None, caption='', directory='', 
                        filter='', initialFilter='', options=None):
    def updateText():
        # update the contents of the line edit widget with the selected files
        selected = []
        for index in view.selectionModel().selectedRows():
            selected.append('"{}"'.format(index.data()))
        lineEdit.setText(' '.join(selected))

    dialog = QtWidgets.QFileDialog(parent, windowTitle=caption)
    dialog.setFileMode(dialog.ExistingFiles)
    if options:
        dialog.setOptions(options)
    dialog.setOption(dialog.DontUseNativeDialog, True)
    if directory:
        dialog.setDirectory(directory)
    if filter:
        dialog.setNameFilter(filter)
        if initialFilter:
            dialog.selectNameFilter(initialFilter)

    # by default, if a directory is opened in file listing mode, 
    # QFileDialog.accept() shows the contents of that directory, but we 
    # need to be able to "open" directories as we can do with files, so we 
    # just override accept() with the default QDialog implementation which 
    # will just return exec_()
    dialog.accept = lambda: QtWidgets.QDialog.accept(dialog)

    # there are many item views in a non-native dialog, but the ones displaying 
    # the actual contents are created inside a QStackedWidget; they are a 
    # QTreeView and a QListView, and the tree is only used when the 
    # viewMode is set to QFileDialog.Details, which is not this case
    stackedWidget = dialog.findChild(QtWidgets.QStackedWidget)
    view = stackedWidget.findChild(QtWidgets.QListView)
    view.selectionModel().selectionChanged.connect(updateText)

    lineEdit = dialog.findChild(QtWidgets.QLineEdit)
    # clear the line edit contents whenever the current directory changes
    dialog.directoryEntered.connect(lambda: lineEdit.setText(''))

    dialog.exec_()
    return dialog.selectedFiles()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM