92
92
}
93
93
94
94
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 ()))
97
100
98
101
102
+ # lru_cache keeps a reference to the QApplication instance, keeping it from
103
+ # being GC'd.
104
+ @functools .lru_cache (1 )
99
105
def _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' )
151
122
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 ()
153
154
154
155
try :
155
- qApp .setAttribute (QtCore .Qt .AA_UseHighDpiPixmaps ) # Only for Qt<6.
156
+ app .setAttribute (QtCore .Qt .AA_UseHighDpiPixmaps ) # Only for Qt<6.
156
157
except AttributeError :
157
158
pass
158
159
160
+ return app
161
+
159
162
160
163
def _allow_super_init (__init__ ):
161
164
"""
@@ -419,7 +422,7 @@ def _get_key(self, event):
419
422
420
423
def flush_events (self ):
421
424
# docstring inherited
422
- qApp .processEvents ()
425
+ QtWidgets . QApplication . instance () .processEvents ()
423
426
424
427
def start_event_loop (self , timeout = 0 ):
425
428
# docstring inherited
@@ -1022,7 +1025,7 @@ def trigger(self, *args):
1022
1025
class ToolCopyToClipboardQT (backend_tools .ToolCopyToClipboardBase ):
1023
1026
def trigger (self , * args , ** kwargs ):
1024
1027
pixmap = self .canvas .grab ()
1025
- qApp .clipboard ().setPixmap (pixmap )
1028
+ QtWidgets . QApplication . instance () .clipboard ().setPixmap (pixmap )
1026
1029
1027
1030
1028
1031
FigureManagerQT ._toolbar2_class = NavigationToolbar2QT
@@ -1036,5 +1039,6 @@ class _BackendQT(_Backend):
1036
1039
1037
1040
@staticmethod
1038
1041
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