![](/img/trans.png)
[英]Is there a difference between QFileDialog strings in PyQt4 and PyQt5?
[英]QFileDialog - differences between PyQt4/PyQt5/PySide
我一直在阅读关于使用 Python 和 QT 进行快速 GUI 编程的 Summerfields 书(更准确地说是 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
应该返回什么。
我错过了什么?
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
的签名getSaveFileName
为返回元组会造成太多破坏,因此添加了getSaveFileNameAndFilter
函数作为临时妥协。
PyQt5 没有这样的限制(它甚至不再需要提供QString
)。 所以终于有可能做正确的事情(从 Python 的角度来看)并且只从getSaveFileName
返回一个元组。 这个原则现在普遍适用:如果您使用 PyQt5,并且您在 Qt 文档中看到一个修改其参数的函数,您总是可以期望返回一个元组。
(PS:PySide 的用户——它比 PyQt 年轻得多——从来不必处理这些问题。对他们来说,静态QFileDialog
函数总是做正确的事情)。
QFileDialog
这些方法看起来有点特别,因为 PyQt 已经实现了自己的方法,而不是直接包装 Qt 方法。
首先,PyQt5 QFileDialog.getSaveFileName()
方法实现的行为QFileDialog.getSaveFileNameAndFilter()
方法从PyQt4的( 源)。 其次,PyQt4 中的QFileDialog.getSaveFileNameAndFilter()
方法返回一个(filename, selectedFilter)
( source ) 的元组。
作为参考,PyQt4 QFileDialog.getSaveFileNameAndFilter()
方法的调用签名是
getSaveFileNameAndFilter (QWidget parent = None, QString caption = QString(),
QString directory = QString(), QString filter = QString(),
QString initialFilter = QString(), Options options = 0)
希望这有助于解决任何混淆。 大多数 PyQt5 类/方法在解码时不会如此混乱!
使用以下语法(添加昏迷和下划线)可以绕过解决 getSaveFileName 方法(使用 PyQt5)的“元组问题”:
fname, _ = QFileDialog.getSaveFileName(self,
"Image Changer - Save Image", fname,
"Image files ({})".format(" ".join(formats)))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.