9292}
9393
9494
95- # make place holder
96- qApp = None
95+ @_api .caching_module_getattr
96+ class __getattr__ :
97+ qApp = _api .deprecated (
98+ "3.6" , alternative = "QtWidgets.QApplication.instance()" )(
99+ property (lambda self : QtWidgets .QApplication .instance ()))
97100
98101
102+ # lru_cache keeps a reference to the QApplication instance, keeping it from
103+ # being GC'd.
104+ @functools .lru_cache (1 )
99105def _create_qApp ():
100- """
101- Only one qApp can exist at a time, so check before creating one.
102- """
103- global qApp
104-
105- if qApp is None :
106- app = QtWidgets .QApplication .instance ()
107- if app is None :
108- # display_is_valid returns False only if on Linux and neither X11
109- # nor Wayland display can be opened.
110- if not mpl ._c_internal_utils .display_is_valid ():
111- raise RuntimeError ('Invalid DISPLAY variable' )
112- try :
113- QtWidgets .QApplication .setAttribute (
114- QtCore .Qt .AA_EnableHighDpiScaling )
115- except AttributeError : # Only for Qt>=5.6, <6.
116- pass
117-
118- # Check to make sure a QApplication from a different major version
119- # of Qt is not instantiated in the process
120- if QT_API in {'PyQt6' , 'PySide6' }:
121- other_bindings = ('PyQt5' , 'PySide2' )
122- elif QT_API in {'PyQt5' , 'PySide2' }:
123- other_bindings = ('PyQt6' , 'PySide6' )
124- else :
125- raise RuntimeError ("Should never be here" )
126-
127- for binding in other_bindings :
128- mod = sys .modules .get (f'{ binding } .QtWidgets' )
129- if mod is not None and mod .QApplication .instance () is not None :
130- other_core = sys .modules .get (f'{ binding } .QtCore' )
131- _api .warn_external (
132- f'Matplotlib is using { QT_API } which wraps '
133- f'{ QtCore .qVersion ()} however an instantiated '
134- f'QApplication from { binding } which wraps '
135- f'{ other_core .qVersion ()} exists. Mixing Qt major '
136- 'versions may not work as expected.'
137- )
138- break
139- try :
140- QtWidgets .QApplication .setHighDpiScaleFactorRoundingPolicy (
141- QtCore .Qt .HighDpiScaleFactorRoundingPolicy .PassThrough )
142- except AttributeError : # Only for Qt>=5.14.
143- pass
144- qApp = QtWidgets .QApplication (["matplotlib" ])
145- if sys .platform == "darwin" :
146- image = str (cbook ._get_data_path ('images/matplotlib.svg' ))
147- icon = QtGui .QIcon (image )
148- qApp .setWindowIcon (icon )
149- qApp .lastWindowClosed .connect (qApp .quit )
150- cbook ._setup_new_guiapp ()
106+ app = QtWidgets .QApplication .instance ()
107+
108+ # Create a new QApplication and configure if if non exists yet, as only one
109+ # QApplication can exist at a time.
110+ if app is None :
111+ # display_is_valid returns False only if on Linux and neither X11
112+ # nor Wayland display can be opened.
113+ if not mpl ._c_internal_utils .display_is_valid ():
114+ raise RuntimeError ('Invalid DISPLAY variable' )
115+
116+ # Check to make sure a QApplication from a different major version
117+ # of Qt is not instantiated in the process
118+ if QT_API in {'PyQt6' , 'PySide6' }:
119+ other_bindings = ('PyQt5' , 'PySide2' )
120+ elif QT_API in {'PyQt5' , 'PySide2' }:
121+ other_bindings = ('PyQt6' , 'PySide6' )
151122 else :
152- qApp = app
123+ raise RuntimeError ("Should never be here" )
124+
125+ for binding in other_bindings :
126+ mod = sys .modules .get (f'{ binding } .QtWidgets' )
127+ if mod is not None and mod .QApplication .instance () is not None :
128+ other_core = sys .modules .get (f'{ binding } .QtCore' )
129+ _api .warn_external (
130+ f'Matplotlib is using { QT_API } which wraps '
131+ f'{ QtCore .qVersion ()} however an instantiated '
132+ f'QApplication from { binding } which wraps '
133+ f'{ other_core .qVersion ()} exists. Mixing Qt major '
134+ 'versions may not work as expected.'
135+ )
136+ break
137+ try :
138+ QtWidgets .QApplication .setAttribute (
139+ QtCore .Qt .AA_EnableHighDpiScaling )
140+ except AttributeError : # Only for Qt>=5.6, <6.
141+ pass
142+ try :
143+ QtWidgets .QApplication .setHighDpiScaleFactorRoundingPolicy (
144+ QtCore .Qt .HighDpiScaleFactorRoundingPolicy .PassThrough )
145+ except AttributeError : # Only for Qt>=5.14.
146+ pass
147+ app = QtWidgets .QApplication (["matplotlib" ])
148+ if sys .platform == "darwin" :
149+ image = str (cbook ._get_data_path ('images/matplotlib.svg' ))
150+ icon = QtGui .QIcon (image )
151+ app .setWindowIcon (icon )
152+ app .lastWindowClosed .connect (app .quit )
153+ cbook ._setup_new_guiapp ()
153154
154155 try :
155- qApp .setAttribute (QtCore .Qt .AA_UseHighDpiPixmaps ) # Only for Qt<6.
156+ app .setAttribute (QtCore .Qt .AA_UseHighDpiPixmaps ) # Only for Qt<6.
156157 except AttributeError :
157158 pass
158159
160+ return app
161+
159162
160163def _allow_super_init (__init__ ):
161164 """
@@ -419,7 +422,7 @@ def _get_key(self, event):
419422
420423 def flush_events (self ):
421424 # docstring inherited
422- qApp .processEvents ()
425+ QtWidgets . QApplication . instance () .processEvents ()
423426
424427 def start_event_loop (self , timeout = 0 ):
425428 # docstring inherited
@@ -1022,7 +1025,7 @@ def trigger(self, *args):
10221025class ToolCopyToClipboardQT (backend_tools .ToolCopyToClipboardBase ):
10231026 def trigger (self , * args , ** kwargs ):
10241027 pixmap = self .canvas .grab ()
1025- qApp .clipboard ().setPixmap (pixmap )
1028+ QtWidgets . QApplication . instance () .clipboard ().setPixmap (pixmap )
10261029
10271030
10281031FigureManagerQT ._toolbar2_class = NavigationToolbar2QT
@@ -1036,5 +1039,6 @@ class _BackendQT(_Backend):
10361039
10371040 @staticmethod
10381041 def mainloop ():
1039- with _maybe_allow_interrupt (qApp ):
1040- qt_compat ._exec (qApp )
1042+ qapp = QtWidgets .QApplication .instance ()
1043+ with _maybe_allow_interrupt (qapp ):
1044+ qt_compat ._exec (qapp )
0 commit comments