PyQt4和PyQt5之间的差异

PyQt5 不兼容 PyQt4 (尽管事实证明将程序从PyQt4移植到PyQt5并不困难). 本节描述了两者之间的主要差异.

支持的Python版本

仅支持Python2.6以后的版本

弃用的功能

PyQt5不支持在Qt v5.0中被标记为弃用或废弃的Qt API的任何部分。然而,其中一些可能偶然包含在内。这些被认为是错误,如果发现将被删除。

Multiple APIs

PyQt4 supports a number of different API versions (QString, QVariant etc.). QVariant外,PyQt5仅为所有版本的Python实现了这些API的v2。The changed support for QVariant, including the removal of QPyNullVariant, is described in Support for QVariant.

旧式信号和槽

PyQt4’s old-style signals and slots are not supported. Therefore the following are not implemented in PyQt5:

  • QObject.connect()
  • QObject.emit()
  • SIGNAL()
  • SLOT()

All methods that had arguments that are usually the results of calls to SIGNAL() or SLOT() are no longer supported. There will always be an equivalent that takes a bound signal or callable respectively.

In addition the following methods have differences:

  • disconnect() takes no arguments and disconnects all connections to the QObject instance.

新式信号和插槽

Qt将带有可选参数的信号作为两个独立的信号来实现,一个带有参数,另一个没有参数。PyQt4 exposed both of these allowing you to connect to each of them. 但是,在发射信号时,必须使用适合发射参数数量的信号。

PyQt5只显示所有参数被指定的信号。但是,它允许在发送信号时省略任何可选参数。

与PyQt4不同,PyQt5支持从QObject(即在mixin中)未分类的类中的属性,信号和时隙的定义。

QtDeclarativeQtScriptQtScriptTools模块

不支持PyQt4的QtDeclarativeQtScriptQtScriptTools模块。这些已被PyQt5的QtQmlQtQuick模块取代。与PyQt4不同,PyQt5支持从QML创建Python对象。

QtGui模块

PyQt4的QtGui模块已被分割为PyQt5的QtGuiQtPrintSupportQtWidgets模块。

QtOpenGL模块

PyQt5仅支持QGLContextQGLFormatQGLWidget类。

QtWebKit模块

PyQt4’s QtWebKit module has been split into PyQt5’s QtWebKit and QtWebKitWidgets modules.

pyqtconfig模块

PyQt4’s pyqtconfig module is not supported. The section The PyQt5 Extension API describes the support that PyQt5 provides to third-party packages (e.g. QScintilla) that want to build on top of PyQt5.

dbus.mainloop.qt模块¶

PyQt4的dbus.mainloop.qt模块在PyQt5中称为dbus.mainloop.pyqt5。 这允许它们并排安装。它们的功能是相同的。

QDataStream

The readUInt8(), readInt8(), writeUInt8() and writeInt8() methods all interpret the values being read and written as numeric values. In PyQt4 they are interpreted as single character strings.

QFileDialog

The getOpenFileNameAndFilter(), getOpenFileNamesAndFilter() and getSaveFileNameAndFilter() methods of PyQt4’s QFileDialog have now been renamed getOpenFileName(), getOpenFileNames() and getSaveFileName() respectively in PyQt5. PyQt4’s implementations of getOpenFileName(), getOpenFileNames() and getSaveFileName() are not supported in PyQt5.

QGraphicsItemAnimation

Support for the deprecated QGraphicsItemAnimation class has been removed. If porting an existing PyQt4 application then consider first updating it to use QPropertyAnimation instead.

QMatrix

Support for the deprecated QMatrix class has been removed. If porting an existing PyQt4 application then consider first updating it to use QTransform instead.

QPyTextObject

PyQt4 implements the QPyTextObject as a workaround for the inability to define a Python class that is sub-classed from more than one Qt class. PyQt5 does support the ability to define a Python class that is sub-classed from more than one Qt class so long as all but one of the Qt classes are interfaces, i.e. they have been declared in C++ as such using Q_DECLARE_INTERFACE. Therefore QPyTextObject is not implemented in PyQt5.

QSet

In PyQt4, QSet was implemented as a list in Python v2 and a set in Python v3. In PyQt5 QSet is always implemented as a set.

pyuic5

pyuic5 does not support the --pyqt3-wrapper flag of pyuic4.

pyrcc5

pyrcc5 does not support the -py2 and -py3 flags of pyrcc4. The output of pyrcc5 is compatible with all versions of Python starting with Python v2.6.

Cooperative Multi-inheritance

与PyQt4不同,PyQt5类实现了协作式多重继承。换句话说,PyQt5类在它们的__ init __方法中(其中kwds是未使用的关键字参数的字典)总是与以下Python v3代码等效:

super().__init__(**kwds)

这意味着这些未使用的关键字参数被传递给任何mixin类的__ init __方法。这些mixin类必须合作,即如果他们有自己的__ init __实现,他们必须进行类似的调用。

在PyQt4中使用多重继承时,通常会显式调用超类的__ init __方法,例如:

class MyQObject(QObject, MyMixin):
    def __init__(self, parent, mixin_arg):
        QObject.__init__(self, parent)
        MyMixin.__init__(self, mixin_arg)

        # Other initialisation...

在PyQt5中,上面的代码会导致MyMixin .__ init __被调用两次。相反,它应该实施如下:

class MyQObject(QObject, MyMixin):
    def __init__(self, **kwds):
        super().__init__(**kwds)

        # Other initialisation...

Note that if there is no other initialisation to do then the __init__ method isn’t actually needed.

The mixin class should be implemented as follows:

class MyMixin:
    def __init__(self, mixin_arg, **kwds):
        super().__init__(**kwds)

        # Other initialisation...

If a class only inherits from a single class then it can still call the super-class’s __init__ method explicitly (although it is recommended to use super()).

See Support for Cooperative Multi-inheritance.

Releasing the GIL

The GIL is only released when it is known to be needed. PyQt4 always released the GIL when calling Qt.

退出时对象销毁

When the Python interpreter exits PyQt4 (by default) calls the C++ destructor of all wrapped instances that it owns. This happens in a random order and can therefore cause the interpreter to crash. This behavior can be disabled by calling the sip.setdestroyonexit() function. PyQt5 always calls sip.setdestroyonexit() automatically.