繁体   English   中英

QFileDialog - PyQt4/PyQt5/PySide 之间的差异

[英]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.

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