PyQt/PySide:QFileDialog 用于选择现有和不存在的目录

问题描述 投票:0回答:1

在我的 Python GUI(PyQt/PySide)应用程序中,我使用

QFileDialog
让用户选择 ONLY 一个目录,以便应用程序将在该目录中保存多个文件。该目录可以是现有的,也可以是不存在的。如果该目录不存在,我的应用程序将通过
os.makedirs(dir)

为用户创建目录

所以最初,我用这个来打开

QFileDialog

dir = QFileDialog.getExistingDirectory(self, "Please pick a directory...", path)

这将限制用户只能选择目录而不是文件。但是,这不允许用户选择不存在的目录。所以我不得不把它改成这样:

dir, _filter = QFileDialog.getSaveFileName(self, "Please pick a directory...", path, "Directory", "", QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)

这样,我允许用户“保存”一个新目录。但是,这不允许用户选择现有目录。 (另外,如果我希望用户只看到目录,我不确定上面的过滤器是否正确)

通过坚持

QFileDialog
的静态函数,有没有办法让我允许用户选择一个可以存在或不存在的目录?

如果我必须进入非静态函数路径才能实现这一点,我可能需要更多帮助,因为我没有使用

QFileDialog
的非静态函数的经验。欢迎一些示例代码,因为我不知道如何设置尽可能接近本机文件对话框的
QFileDialog

python directory pyqt pyside qfiledialog
1个回答
0
投票

这无法通过静态函数实现,因为它们是仅提供标准和常见行为的辅助函数。

由于它也是一种自定义行为,因此只能使用非本机对话框来实现:虽然某些系统可能提供一种“选择”不存在目录的方法,但目录对话框通常不希望这样做。

您必须使用 QFileDialog 子类并更改其一些行为:

  • 确保即使在路径字段中输入不存在的路径时也启用“选择”按钮;
  • 允许接受文件对话框,即使所选路径不存在;

为了实现第一个目标,您需要访问对话框的两个小部件:路径字段和选择按钮。

幸运的是,QFileDialog 是使用标准设计器 UI 构建的,每个小部件都有自己的

objectName
,允许我们使用
findChild()
:

访问它们
  • 路径字段为
    fileNameEdit
    ;
  • “接受”按钮是 QDialogButtonBox 的
    Save
    按钮;

然后,我们将

textChanged
信号连接到一个自定义函数,该函数检查当前文本是否引用现有目录或不存在的路径;请注意,QFileDialog 已经将该信号连接到内部函数,允许选择空路径,指示当前可见的目录,因此我们只需要在按钮先前被禁用的情况下进行上述检查。

最后,我们需要重写对话框的

accept()
函数。以类似的方式,如果行编辑中没有输入路径,我们调用默认行为,否则我们检查它是否是目录或路径不存在。

class SelectDirDialog(QFileDialog):
    def __init__(self, parent, caption='', path=''):
        super().__init__(parent)
        # DontUseNativeDialog must be set before anything else
        self.setOptions(self.DontUseNativeDialog)

        # the following order is important: AcceptSave automatically changes
        # the title to "Save as" (or its translation), while we need the 
        # possible default for the AcceptOpen in Directory mode
        self.setFileMode(self.Directory)
        title = caption or self.windowTitle()
        self.setAcceptMode(self.AcceptSave)
        self.setWindowTitle(title)

        self.setDirectory(path or QDir.currentPath())

        self.fileNameEdit = self.findChild(QLineEdit, 'fileNameEdit')
        self.fileNameEdit.textChanged.connect(self.checkOkButton)
        self.okButton = self.findChild(QDialogButtonBox).button(
            QDialogButtonBox.Save)

    def accept(self):
        files = self.selectedFiles()
        if not files:
            super().accept()
            return

        info = QFileInfo(files[0])
        if info.isDir() or not info.exists():
            QDialog.accept(self)

    def checkOkButton(self):
        if self.okButton.isEnabled():
            return
        info = QFileInfo(self.fileNameEdit.text())
        self.okButton.setEnabled(info.isDir() or not info.exists())

    def selectedPath(self):
        files = self.selectedFiles()
        return files[0] if files else ''


...

dlg = SelectDirDialog(self)
if dlg.exec():
    print(dlg.selectedPath())
© www.soinside.com 2019 - 2024. All rights reserved.