diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index d9a4447744a0..ac19d29884c4 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -2293,7 +2293,7 @@ def start_event_loop(self, timeout=0): The event loop blocks until a callback function triggers `stop_event_loop`, or *timeout* is reached. - If *timeout* is negative, never timeout. + If *timeout* is 0 or negative, never timeout. Only interactive backends need to reimplement this method and it relies on `flush_events` being properly implemented. diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 718c005f1f0d..dc4f6e26b066 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -15,10 +15,12 @@ import matplotlib.backends.qt_editor.figureoptions as figureoptions from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool from matplotlib.backend_managers import ToolManager - +from . import qt_compat from .qt_compat import ( QtCore, QtGui, QtWidgets, _isdeleted, _getSaveFileName, - is_pyqt5, __version__, QT_API) + is_pyqt5, __version__, QT_API, _setDevicePixelRatioF, + _devicePixelRatioF) + backend_version = __version__ @@ -267,12 +269,7 @@ def _update_figure_dpi(self): @property def _dpi_ratio(self): - # Not available on Qt4 or some older Qt5. - try: - # self.devicePixelRatio() returns 0 in rare cases - return self.devicePixelRatio() or 1 - except AttributeError: - return 1 + return _devicePixelRatioF(self) def _update_dpi(self): # As described in __init__ above, we need to be careful in cases with @@ -454,8 +451,9 @@ def start_event_loop(self, timeout=0): if hasattr(self, "_event_loop") and self._event_loop.isRunning(): raise RuntimeError("Event loop already running") self._event_loop = event_loop = QtCore.QEventLoop() - if timeout: - timer = QtCore.QTimer.singleShot(timeout * 1000, event_loop.quit) + if timeout > 0: + timer = QtCore.QTimer.singleShot(int(timeout * 1000), + event_loop.quit) event_loop.exec_() def stop_event_loop(self, event=None): @@ -683,8 +681,7 @@ def _icon(self, name, color=None): if is_pyqt5(): name = name.replace('.png', '_large.png') pm = QtGui.QPixmap(os.path.join(self.basedir, name)) - if hasattr(pm, 'setDevicePixelRatio'): - pm.setDevicePixelRatio(self.canvas._dpi_ratio) + _setDevicePixelRatioF(pm, _devicePixelRatioF(self)) if color is not None: mask = pm.createMaskFromColor(QtGui.QColor('black'), QtCore.Qt.MaskOutColor) diff --git a/lib/matplotlib/backends/backend_qt5agg.py b/lib/matplotlib/backends/backend_qt5agg.py index 09a2a261844d..f4d7842cbd1f 100644 --- a/lib/matplotlib/backends/backend_qt5agg.py +++ b/lib/matplotlib/backends/backend_qt5agg.py @@ -11,7 +11,7 @@ from .backend_qt5 import ( QtCore, QtGui, QtWidgets, _BackendQT5, FigureCanvasQT, FigureManagerQT, NavigationToolbar2QT, backend_version) -from .qt_compat import QT_API +from .qt_compat import QT_API, _setDevicePixelRatioF class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT): @@ -64,9 +64,7 @@ def paintEvent(self, event): qimage = QtGui.QImage(buf, buf.shape[1], buf.shape[0], QtGui.QImage.Format_ARGB32_Premultiplied) - if hasattr(qimage, 'setDevicePixelRatio'): - # Not available on Qt4 or some older Qt5. - qimage.setDevicePixelRatio(self._dpi_ratio) + _setDevicePixelRatioF(qimage, self._dpi_ratio) # set origin using original QT coordinates origin = QtCore.QPoint(rect.left(), rect.top()) painter.drawImage(origin, qimage) @@ -87,7 +85,7 @@ def blit(self, bbox=None): bbox = self.figure.bbox # repaint uses logical pixels, not physical pixels like the renderer. - l, b, w, h = [pt / self._dpi_ratio for pt in bbox.bounds] + l, b, w, h = [int(pt / self._dpi_ratio) for pt in bbox.bounds] t = b + h self.repaint(l, self.renderer.height / self._dpi_ratio - t, w, h) diff --git a/lib/matplotlib/backends/backend_qt5cairo.py b/lib/matplotlib/backends/backend_qt5cairo.py index 5a38a80864be..d29997410323 100644 --- a/lib/matplotlib/backends/backend_qt5cairo.py +++ b/lib/matplotlib/backends/backend_qt5cairo.py @@ -2,7 +2,7 @@ from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo from .backend_qt5 import QtCore, QtGui, _BackendQT5, FigureCanvasQT -from .qt_compat import QT_API +from .qt_compat import QT_API, _setDevicePixelRatioF class FigureCanvasQTCairo(FigureCanvasQT, FigureCanvasCairo): @@ -19,8 +19,8 @@ def draw(self): def paintEvent(self, event): self._update_dpi() dpi_ratio = self._dpi_ratio - width = dpi_ratio * self.width() - height = dpi_ratio * self.height() + width = int(dpi_ratio * self.width()) + height = int(dpi_ratio * self.height()) if (width, height) != self._renderer.get_canvas_width_height(): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) self._renderer.set_ctx_from_surface(surface) @@ -33,9 +33,7 @@ def paintEvent(self, event): # QImage under PySide on Python 3. if QT_API == 'PySide': ctypes.c_long.from_address(id(buf)).value = 1 - if hasattr(qimage, 'setDevicePixelRatio'): - # Not available on Qt4 or some older Qt5. - qimage.setDevicePixelRatio(dpi_ratio) + _setDevicePixelRatioF(qimage, dpi_ratio) painter = QtGui.QPainter(self) painter.eraseRect(event.rect()) painter.drawImage(0, 0, qimage) diff --git a/lib/matplotlib/backends/qt_compat.py b/lib/matplotlib/backends/qt_compat.py index 2a4a3aa53629..906845a68096 100644 --- a/lib/matplotlib/backends/qt_compat.py +++ b/lib/matplotlib/backends/qt_compat.py @@ -173,4 +173,38 @@ def is_pyqt5(): # These globals are only defined for backcompatibility purposes. ETS = dict(pyqt=(QT_API_PYQTv2, 4), pyside=(QT_API_PYSIDE, 4), pyqt5=(QT_API_PYQT5, 5), pyside2=(QT_API_PYSIDE2, 5)) -QT_RC_MAJOR_VERSION = 5 if is_pyqt5() else 4 + +QT_RC_MAJOR_VERSION = int(QtCore.qVersion().split(".")[0]) + + +def _devicePixelRatioF(obj): + """ + Return obj.devicePixelRatioF() with graceful fallback for older Qt. + + This can be replaced by the direct call when we require Qt>=5.6. + """ + try: + # Not available on Qt<5.6 + return obj.devicePixelRatioF() or 1 + except AttributeError: + pass + try: + # Not available on Qt4 or some older Qt5. + # self.devicePixelRatio() returns 0 in rare cases + return obj.devicePixelRatio() or 1 + except AttributeError: + return 1 + + +def _setDevicePixelRatioF(obj, val): + """ + Call obj.setDevicePixelRatioF(val) with graceful fallback for older Qt. + + This can be replaced by the direct call when we require Qt>=5.6. + """ + if hasattr(obj, 'setDevicePixelRatioF'): + # Not available on Qt<5.6 + obj.setDevicePixelRatioF(val) + elif hasattr(obj, 'setDevicePixelRatio'): + # Not available on Qt4 or some older Qt5. + obj.setDevicePixelRatio(val) diff --git a/lib/matplotlib/tests/test_backend_qt.py b/lib/matplotlib/tests/test_backend_qt.py index e0c0a3b2010f..c49af2ddfbbc 100644 --- a/lib/matplotlib/tests/test_backend_qt.py +++ b/lib/matplotlib/tests/test_backend_qt.py @@ -253,6 +253,29 @@ def test_dpi_ratio_change(): assert qt_canvas.get_width_height() == (600, 240) assert (fig.get_size_inches() == (5, 2)).all() + p.return_value = 1.5 + + assert qt_canvas._dpi_ratio == 1.5 + + qt_canvas.draw() + qApp.processEvents() + # this second processEvents is required to fully run the draw. + # On `update` we notice the DPI has changed and trigger a + # resize event to refresh, the second processEvents is + # required to process that and fully update the window sizes. + qApp.processEvents() + + # The DPI and the renderer width/height change + assert fig.dpi == 180 + assert qt_canvas.renderer.width == 900 + assert qt_canvas.renderer.height == 360 + + # The actual widget size and figure physical size don't change + assert size.width() == 600 + assert size.height() == 240 + assert qt_canvas.get_width_height() == (600, 240) + assert (fig.get_size_inches() == (5, 2)).all() + @pytest.mark.backend('Qt5Agg') def test_subplottool(): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy