web-dev-qa-db-ja.com

qAppとQApplication.instance()

PyQt5では、これらの両方がアプリケーションオブジェクトを返します。

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

しかし、なぜprint(QtWidgets.QApplication.instance() is QtWidgets.qApp)Falseを出力するのですか?

11
Sir Visto

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

したがって、QApplicationオブジェクトがまだ作成されていなくても、qApp変数はQApplicationインスタンスを指します。モジュールがクラスに似ていて、動的なプロパティを持つことができる場合、qAppQApplication.instance()とまったく同じように機能し、最初はNoneを返す可能性があります。ただし、静的であるため、常に正しい型のオブジェクトを返す必要があります。これにより、後でQApplication.instance()と同じ基になるC++オブジェクトを参照できるようになります。

ただし、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
_

ただし、QApplicationが作成されると、どちらも同じものを指します。

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

したがって、_(QtWidgets.QApplication.instance() is QtWidgets.qApp)_がFalseを返す理由は、2つのオブジェクトが異なるpython同じ基になるC++オブジェクトのラッパーであるためです。

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
_

これを回避する唯一の方法は、qAppモジュール変数を明示的に上書きすることです(そして明らかに、他のモジュールによってインポートされる前にこれが行われることを確認してください):

_>>> QtWidgets.qApp = myapp
>>> QtWidgets.qApp.hello()
Hello World
_
21
ekhumoro