qApp versus QApplication.instance()

廉价感情. 提交于 2020-02-17 13:26:38

问题


With PyQt5, both of these return the application object:

app = QtWidgets.QApplication.instance()
app = QtWidgets.qApp
for i in app.arguments()[1:]:
    ...

But why does print(QtWidgets.QApplication.instance() is QtWidgets.qApp) print False?


回答1:


The difference between QtWidgets.QApplication.instance() and QtWidgets.qApp is that the latter is a static module variable that must be created when the module is first imported. This results in the following initially baffling behaviour:

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

So even though no QApplication object has been created yet, the qApp variable still points to a QApplication instance. If modules were more like classes, so that they could have dynamic properties, it would be possible for qApp to work exactly like QApplication.instance() does and initially return None. But because it is static, it must always return an object of the correct type, so that it can later refer to the same underlying C++ object as QApplication.instance().

However, it's important to note that qApp is initially just an empty wrapper:

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

Once the QApplication is created, though, they will both point to the same thing:

>>> app = QtWidgets.QApplication([])
>>> app.setObjectName('foo')
>>> qapp.objectName()
'foo'

So the reason why (QtWidgets.QApplication.instance() is QtWidgets.qApp) returns False, is that the two objects are different python wrappers around the same underlying C++ object.

It's important to be aware of this point if you ever need to create your own sublass of QApplication, but still want to use 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

The only way around this is to explicitly overwrite the qApp module variable (and obviously ensure that this is done before it can be imported by other modules):

>>> QtWidgets.qApp = myapp
>>> QtWidgets.qApp.hello()
Hello World


来源:https://stackoverflow.com/questions/40400954/qapp-versus-qapplication-instance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!