diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 24f0c24fc02a..90ad4fd477ed 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -17,7 +17,9 @@ from matplotlib.backends.qt_editor._formsubplottool import UiSubplotTool from . import qt_compat from .qt_compat import ( - QtCore, QtGui, QtWidgets, _isdeleted, is_pyqt5, __version__, QT_API) + QtCore, QtGui, QtWidgets, __version__, QT_API, + _devicePixelRatioF, _isdeleted, +) backend_version = __version__ @@ -247,7 +249,7 @@ def _update_figure_dpi(self): @property def _dpi_ratio(self): - return qt_compat._devicePixelRatio(self) + return _devicePixelRatioF(self) def _update_dpi(self): # As described in __init__ above, we need to be careful in cases with @@ -707,7 +709,7 @@ def _icon(self, name): if QtCore.qVersion() >= '5.': name = name.replace('.png', '_large.png') pm = QtGui.QPixmap(str(cbook._get_data_path('images', name))) - qt_compat._setDevicePixelRatio(pm, qt_compat._devicePixelRatio(self)) + qt_compat._setDevicePixelRatio(pm, _devicePixelRatioF(self)) if self.palette().color(self.backgroundRole()).value() < 128: icon_color = self.palette().color(self.foregroundRole()) mask = pm.createMaskFromColor(QtGui.QColor('black'), diff --git a/lib/matplotlib/backends/backend_qt5agg.py b/lib/matplotlib/backends/backend_qt5agg.py index 11b60378ac39..c46e493f9cf1 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) 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 12797b602872..4252dad47335 100644 --- a/lib/matplotlib/backends/qt_compat.py +++ b/lib/matplotlib/backends/qt_compat.py @@ -185,7 +185,41 @@ def _setDevicePixelRatio(obj, factor): pass # 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 = int(QtCore.qVersion().split(".")[0]) if QT_RC_MAJOR_VERSION == 4: mpl.cbook.warn_deprecated("3.3", name="support for Qt4") + + +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) + if 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 e1200adc1935..564192d6ec1d 100644 --- a/lib/matplotlib/tests/test_backend_qt.py +++ b/lib/matplotlib/tests/test_backend_qt.py @@ -213,6 +213,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