qApp与QApplication.instance()

Sir*_*sto 10 python pyqt instance pyqt5 qapplication

使用PyQt5,这两个都返回应用程序对象:

app = QtWidgets.QApplication.instance()
app = QtWidgets.qApp
for i in app.arguments()[1:]:
    ...
Run Code Online (Sandbox Code Playgroud)

但为什么print(QtWidgets.QApplication.instance() is QtWidgets.qApp)打印False

ekh*_*oro 21

QtWidgets.QApplication.instance()和之间的区别在于QtWidgets.qApp后者是一个静态模块变量,必须在首次导入模块时创建.这导致以下最初令人困惑的行为:

>>> from PyQt5 import QtWidgets
>>> inst = QtWidgets.QApplication.instance()
>>> qapp = QtWidgets.qApp
>>> (inst, qapp)
(None, <PyQt5.QtWidgets.QApplication object at 0x7ff3c8bd3948>)
Run Code Online (Sandbox Code Playgroud)

因此,即使QApplication尚未创建任何对象,该qApp变量仍指向QApplication实例.如果模块更像是类,那么它们可以具有动态属性,那么就可以qApp像do一样QApplication.instance()工作并且最初返回None.但是因为它是静态的,所以它必须总是返回一个正确类型的对象,以便稍后可以引用相同的底层C++对象QApplication.instance().

但是,重要的是要注意,qApp最初只是一个包装器:

>>> qapp.objectName()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: wrapped C/C++ object of type QApplication has been deleted
Run Code Online (Sandbox Code Playgroud)

QApplication但是,一旦创建了它们,它们都指向同一个东西:

>>> app = QtWidgets.QApplication([])
>>> app.setObjectName('foo')
>>> qapp.objectName()
'foo'
Run Code Online (Sandbox Code Playgroud)

所以(QtWidgets.QApplication.instance() is QtWidgets.qApp)返回的原因False是两个对象是围绕同一底层C++对象的不同python包装器.

如果您需要创建自己的子类QApplication,但仍想使用qApp以下内容,请务必注意这一点:

>>> from PyQt5 import QtWidgets
>>> class MyApp(QtWidgets.QApplication):
...     def hello(self): print('Hello World')
...
>>> myapp = MyApp([])
>>> myapp.hello()
Hello World
>>>
>>> QtWidgets.qApp
<PyQt5.QtWidgets.QApplication object at 0x7f5e42f40948>
>>> QtWidgets.qApp.hello()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'QApplication' object has no attribute 'hello'
>>>
>>> inst = QtWidgets.QApplication.instance()
>>> inst
<__main__.MyApp object at 0x7f5e42f409d8>
>>> inst.hello()
Hello World
Run Code Online (Sandbox Code Playgroud)

解决此问题的唯一方法是显式覆盖qApp模块变量(显然确保在其他模块导入之前完成此操作):

>>> QtWidgets.qApp = myapp
>>> QtWidgets.qApp.hello()
Hello World
Run Code Online (Sandbox Code Playgroud)