Support fractional HiDpi scaling with Qt backends - #15656
Conversation
11a1a57 to
ea8dfdb
Compare
|
There's an issue with While I will try to fix this in isolation, we must check if other places also need an integer conversion. Also, should we cast to int or round to int? |
|
Probably do the same as what the qt version does? |
ea8dfdb to
c205b60
Compare
| obj.setDevicePixelRatioF(val) | ||
| if hasattr(obj, 'setDevicePixelRatio'): | ||
| # Not available on Qt4 or some older Qt5. | ||
| obj.setDevicePixelRatio(val) |
There was a problem hiding this comment.
do we want to cast to int here?
There was a problem hiding this comment.
I would think so, given your other Qt PR, though that's for new Qt that wouldn't call this. Though I think it would come from getDevicePixelRatio, so we may expect int anyway?
| dpi_ratio = self._dpi_ratio | ||
| width = dpi_ratio * self.width() | ||
| height = dpi_ratio * self.height() | ||
| width = int(dpi_ratio * self.width()) |
There was a problem hiding this comment.
We may want to use round here rather than int to move the jumps away from the integers.
However, this may have issues with not being in sync with what we do else were in the code (which is int).
c205b60 to
eb0068c
Compare
|
It turns out Qt now has an enum to control how it rounds to pixels (https://doc.qt.io/qt-5/qt.html#HighDpiScaleFactorRoundingPolicy-enum). You can test this behavior by setting the import matplotlib.pyplot as plt
import numpy as np
th = np.linspace(0, 2*np.pi, 512)
fig, ax = plt.subplots()
ax.plot(th, np.sin(th))
ax.plot(th, np.cos(th))
ax.set_title(fig.canvas._dpi_ratio)
plt.show()Without this patch it rounds down via truncating for non-integer ratios. I think what is going on is that we are getting the integer version of the dpi scaling and render the figure at (N, M) size. However, the widgets are seeing the fractional part and actually taking up (N1.2, M1.2) pixels on screen. When we paint the rendered figure Qt helpfully re-samples to the actual number of pixels and our anti-aliasing interacts really badly with that. |
tacaswell
left a comment
There was a problem hiding this comment.
Take my review as only 1/2 as I did the rebase.
eb0068c to
c056bfa
Compare
QuLogic
left a comment
There was a problem hiding this comment.
This test always fails for me when run with everything else, so I'm not 100% on this, but it does pass when run by itself.
| obj.setDevicePixelRatioF(val) | ||
| if hasattr(obj, 'setDevicePixelRatio'): | ||
| # Not available on Qt4 or some older Qt5. | ||
| obj.setDevicePixelRatio(val) |
There was a problem hiding this comment.
I would think so, given your other Qt PR, though that's for new Qt that wouldn't call this. Though I think it would come from getDevicePixelRatio, so we may expect int anyway?
|
I don‘t have the time to look into this in the next couple of days. Anybody can take over and push to this PR if necessary. |
Author: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
c056bfa to
17ff6ba
Compare
| if hasattr(obj, 'setDevicePixelRatioF'): | ||
| # Not available on Qt<5.6 | ||
| obj.setDevicePixelRatioF(val) | ||
| if hasattr(obj, 'setDevicePixelRatio'): |
There was a problem hiding this comment.
This should be elif, no? Or you'll set pixel ratio two different ways.
|
arghh.sorry @QuLogic |
|
Owee, I'm MrMeeseeks, Look at me. There seem to be a conflict, please backport manually. Here are approximate instructions:
And apply the correct labels and milestones. Congratulation you did some good work ! Hopefully your backport PR will be tested by the continuous integration and merged soon! If these instruction are inaccurate, feel free to suggest an improvement. |
…t backends Merge pull request matplotlib#15656 from timhoffm/qt-fractional-hidpi Support fractional HiDpi scaling with Qt backends Conflicts: lib/matplotlib/backends/backend_qt5.py lib/matplotlib/backends/qt_compat.py - only backport relevant changes
|
@timhoffm Actually, is the setDevicePixelRatioF shim ever used? AFAICT there's only |
|
@anntzer You are probably right. I probably did the getter first and assumed that the setter follows the same pattern. td;dr: Additional findings on the getter Digging a bit deeper: It seems that However, the derived classes I was about to propose that we could replace So indeed we could use |
PR Summary
We need to use the floating point versions
devicePixelRatioFinstead ofdevicePixelRatioto scale the canvas correctly when the system uses a fractional scaling.Since we support older Qt versions, setting and getting
devicePixelRatioFis wrapped in helper functions that fall back to the integer version or even no scaling.Tested with a scaling factor of 1.2:
before:

after:

PR Checklist