QFileDialog - PyQt4/PyQt5/PySide 之间的差异 [英] QFileDialog - differences between PyQt4/PyQt5/PySide

查看:99
本文介绍了QFileDialog - PyQt4/PyQt5/PySide 之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

 fname = QFileDialog.getSaveFileName(self,图像转换器 - 保存图像",fname,"图像文件 ({})".format("".join(formats)))

这不起作用,可能主要是因为在 PyQt5 中 QFileDialog 返回一个元组而不是一个字符串.我能解决这个问题的唯一方法就是反复试验.PyQt5 文档指的是 QT,我真的不明白.

我有以下工作:

 fname = QFileDialog.getSaveFileName(self, 'some text',whatever.png"、*.png")如果."不在 fname[0] 中:fname[0] += ".png";self.addRecentFile(fname[0])self.filename = fname[0]返回 self.fileSave()

哇,它有效!但只有通过努力,我才能取得任何进展.我尝试运行 python 解释器并输入:

from PyQt5.QtWidgets import QFileDialog帮助(QFileDialog)

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

我错过了什么?

解决方案

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

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

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

getSaveFileName(QWidget * parent = 0, const QString &标题 = 字符串(),const QString &dir = QString(), const QString &过滤器 = QString(),QString * selectedFilter = 0,选项选项 = 0)

如您所见,四个 QString 参数并不完全相同.前三个是 const,所以不会被函数修改,但是 selectedFilter 参数需要一个指向 QString 的指针,它表示可以.

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

<预><代码>>>>s = QString() # 要修改的字符串>>>f = QFileDialog.getSaveFileName(None, 'Save', '', 'Img(*.png *.jpg)', s)>>>印刷img(*.png *.jpg)

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

PyQt4 多年来稳步引入了许多变化,这些变化逐渐使它对 Python 越来越友好 - 但如上例所示,这一切都没有破坏向后兼容性.当时,将 getSaveFileName 的签名更改为返回元组会造成太多破坏,因此添加了诸如 getSaveFileNameAndFilter 之类的函数作为临时妥协.>

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

<小时>

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

I have been working my way through Summerfields book on Rapid GUI programming with Python and QT (PyQt to be more precise), but the book from 2007 uses version 4.x and I am trying to get going with the current version (5.4.2).

There are some changes that I am trying to figure out and would love some assistance on how to find stuff. Here is an example for a file save dialog - from the book:

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

This does not work, perhaps primarily because in PyQt5 the QFileDialog returns a tuple rather than a string. The only way I can figure this out is just by trial and error. The PyQt5 documentation refers you to QT, which I really do not understand.

I got the following to work:

   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()

Wow, it works! But it is just by slogging through that I get any progress. I tried running python interpreter and typed:

from PyQt5.QtWidgets import  QFileDialog

help(QFileDialog)

This is (sort of) helpful, but the syntax of the help does not make a lot of sense to me, and I do not see what getSaveFileName is supposed to return.

What am I missing?

解决方案

Some of the static functions of QFileDialog have an odd history in PyQt. If you don't know this history, it's hard to make sense of the differences between the various versions of PyQt.

The underlying issue is quite simple. In Python, if a function needs to return more than one value, the most common solution is to return a tuple. But in C++, this is not really possible, so the usual solution is to instead provide arguments that can be modified.

The C++ signature of QFileDialog.getSaveFileName is this:

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

As you can see, the four QString arguments aren't all the same. The first three are const, and so won't be modifed by the function, but the selectedFilter argument takes a pointer to a QString, which means it can be.

Originally, the main use of PyQt was for C++ proto-typing (rather than developing Python applications), and so its APIs were much more faithful to the Qt APIs. This meant that, up until PyQt-4.6, the only way to get the selected filter from QFileDialog, was to do it the C++ way, like this:

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

And in fact, this still works in current versions of PyQt4 (providing it has QString enabled, of course).

PyQt4 steadily introduced a lot of changes that have gradually made it more and more Python-friendly over the years - but as the above example shows, this was all done without breaking backwards-compatibility. At the time, changing the signature of getSaveFileName to return a tuple would have caused far too much breakage, and so functions like getSaveFileNameAndFilter were added as a temporary compromise instead.

PyQt5 does not have such restrictions (it doesn't even need to provide QString anymore). So it has finally become possible to do the right thing (from a Python point of view) and just return a tuple from getSaveFileName. And this principle now applies in general: if you're using PyQt5, and you see a function in the Qt docs that modifies its arguments, you can always expect a tuple to be returned instead.


(PS: users of PySide - which is much younger than PyQt - have never had to deal with these issues. For them, the static QFileDialog functions have always done the right thing).

这篇关于QFileDialog - PyQt4/PyQt5/PySide 之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆