【问题标题】:QFileDialog - differences between PyQt4/PyQt5/PySideQFileDialog - PyQt4/PyQt5/PySide 之间的区别
【发布时间】:2015-06-19 05:53:47
【问题描述】:

我一直在阅读 Summerfields 关于使用 Python 和 QT 进行快速 GUI 编程的书(更准确地说是 PyQt),但是 2007 年的书使用 4.x 版,我正在尝试使用当前版本( 5.4.2)。

我正在尝试找出一些更改,并希望在如何查找内容方面获得一些帮助。这是文件保存对话框的示例 - 来自书中:

    fname = QFileDialog.getSaveFileName(self,
            "Image Changer - Save Image", fname,
            "Image files ({})".format(" ".join(formats)))

这不起作用,可能主要是因为在 PyQt5 中 QFileDialog 返回一个元组而不是一个字符串。我能弄清楚这一点的唯一方法就是反复试验。 PyQt5 文档把你引到 QT,我真的不明白。

我得到了以下工作:

   fname = QFileDialog.getSaveFileName(self, 'some text',
            "whatever.png", '*.png')
   if "." not in fname[0]:
       fname[0] += ".png"
       self.addRecentFile(fname[0])
       self.filename = fname[0]
       return self.fileSave()

哇,好用!但只是通过努力,我得到了任何进展。 我尝试运行 python 解释器并输入:

from PyQt5.QtWidgets import  QFileDialog

help(QFileDialog)

这(有点)有帮助,但帮助的语法对我来说没有多大意义,而且我看不出 getSaveFileName 应该返回什么。

我错过了什么?

【问题讨论】:

  • 这可以帮助你:Reading the Qt Documentation。只是信号和插槽不是最新的(函数connect)。
  • @tmoreau。这似乎来自 2001 年为 PyQt3 写的一本书。

标签: python pyqt pyqt5 pyside qfiledialog


【解决方案1】:

QFileDialog 的一些静态函数在 PyQt 中有一段奇怪的历史。如果您不了解这段历史,就很难理解 PyQt 各个版本之间的差异。

根本问题很简单。在 Python 中,如果一个函数需要返回多个值,最常见的解决方案是返回一个元组。但在 C++ 中,这实际上是不可能的,因此通常的解决方案是提供可修改的参数。

QFileDialog.getSaveFileName 的 C++ 签名是这样的:

getSaveFileName(
    QWidget * parent = 0, const QString & caption = String(),
    const QString & dir = QString(), const QString & filter = QString(),
    QString * selectedFilter = 0, Options options = 0)

如您所见,四个QString 参数并不完全相同。前三个是const,因此不会被函数修改,但selectedFilter 参数需要一个指向QString 的指针,这意味着它可以。

最初,PyQt 的主要用途是用于 C++ 原型设计(而不是开发 Python 应用程序),因此它的 API 更忠实于 Qt API。这意味着,在 PyQt-4.6 之前,从QFileDialog 获取选定过滤器的唯一方法是使用 C++ 方法,如下所示:

>>> s = QString() # string to be modified
>>> f = QFileDialog.getSaveFileName(None, 'Save', '', 'Img(*.png *.jpg)', s)
>>> print s
Img(*.png *.jpg)

事实上,这在当前版本的 PyQt4 中仍然有效(当然,前提是它启用了QString)。

PyQt4 稳步引入了许多变化,这些变化使其多年来对 Python 越来越友好 - 但正如上面的示例所示,这一切都是在 破坏向后兼容性的情况下完成的。当时,将getSaveFileName 的签名更改为返回一个元组会导致过多的损坏,因此添加了getSaveFileNameAndFilter 之类的函数作为临时折衷方案。

PyQt5 没有这样的限制(它甚至不再需要提供QString)。所以终于有可能做正确的事情(从 Python 的角度来看)并从 getSaveFileName 返回一个元组。这个原则现在普遍适用:如果您使用的是 PyQt5,并且您在 Qt 文档中看到一个修改其参数的函数,您总是可以期望返回一个元组。


(PS:PySide 的用户——它比 PyQt 更年轻——从来不用处理这些问题。对他们来说,静态的 QFileDialog 函数总是做正确的事)。

【讨论】:

  • 我不敢相信这从来没有得到任何支持 - 这完美地解释了正在发生的事情,并为我提供了如何解释文档的指导。谢谢!更糟糕的是,如果您没有历史记录并且您访问官方 PyQt5 文档参考,那么 QFileDialog 中的所有内容都是指向 C++ 文档的指针(当然它只返回一个 QString)。注意到可能被修改的参数将是关键!
【解决方案2】:

QFileDialog 的这些方法看起来有点特别,因为 PyQt 实现了自己的方法,而不是直接包装 Qt 方法。

首先,PyQt5 QFileDialog.getSaveFileName() 方法实现了 PyQt4 (source) 中 QFileDialog.getSaveFileNameAndFilter() 方法的行为。其次,PyQt4 中的QFileDialog.getSaveFileNameAndFilter() 方法返回一个元组(filename, selectedFilter)source)。

供参考,PyQt4QFileDialog.getSaveFileNameAndFilter()方法的调用签名为

getSaveFileNameAndFilter (QWidget parent = None, QString caption = QString(), 
                          QString directory = QString(), QString filter = QString(), 
                          QString initialFilter = QString(), Options options = 0)

希望这有助于解决任何困惑。大多数 PyQt5 类/方法都不会如此令人困惑地解码!

【讨论】:

    【解决方案3】:

    解决 getSaveFileName 方法的“元组问题”(使用 PyQt5 )可以使用这种语法绕过(添加逗号和下划线):

    fname, _ = QFileDialog.getSaveFileName(self,
            "Image Changer - Save Image", fname,
            "Image files ({})".format(" ".join(formats)))
    

    【讨论】:

      猜你喜欢
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      • 2016-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多