-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Issue with DPI corrections with Qt5 backend #8052
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Looking into this a bit more - the difference of a factor of 4x in the first example changes to 2x after the plot is shown, which explains why the marker is off by a factor of 2 in the more complex case. |
Does the first example really fix itself after showing the plot? The second bug is unrelated, but easily fixed. I'm not really sure where the width/height come from in the first case. |
@QuLogic - the first example doesn't fix itself, because the display coordinates and canvas size are still mismatched by a factor of 2x after showing (which is basically the problem illustrated in the second example I think) In any case, the only real issue for me is the second example, so just ignore the first example if it's confusing! |
The first bug seems to be related to |
In the case of cs = canvas.sizeHint()
canvas.resize(cs.width(), cs.height()) will get the sizes correct. |
I am seeing a devastating bug with qt5 on a retina display, OSX Sierra, on both master and 2.0.x: zoom/pan, zoom-to-rect, and the cursor readout are completely wrong. I can't investigate right now, but I don't think this has always been the case. |
Bisecting leads to #8144:
|
The problem is that internally mpl lives entirely in the 'real' pixel realm, but Qt lives (except for in the qpainter when we are rendering the plot) in 'logical' pixel space. I think that the two sizes are coming back different is the correct (but super confusing) behavior. To fix the example: from PyQt5 import QtGui, QtWidgets
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class MplCanvas(FigureCanvas):
def __init__(self, fig):
FigureCanvas.__init__(self, fig)
self.renderer = None
self.x = self.y = 0
def paintEvent(self, event):
if self.renderer is None:
self.renderer = self.get_renderer()
super(MplCanvas, self).paintEvent(event)
p = QtGui.QPainter(self)
pen = QtGui.QPen(QtGui.QColor('black'))
pen.setWidth(20)
p.setPen(pen)
p.drawPoint(self.x, self.y)
def mouse_press(self, event):
# convert from data -> screen pixels -> logical pixels
x, y = ax.transData.transform((event.xdata, event.ydata)) / self._dpi_ratio
self.x, self.y = x, self.height() - y
self.update()
app = QtWidgets.QApplication([''])
fig = Figure()
canvas = MplCanvas(fig)
ax = fig.add_axes([0, 0, 1, 1])
print(ax.transData.transform((0.0, 0.0)))
print(ax.transData.transform((0.5, 0.5)))
print(ax.transData.transform((1.0, 1.0)))
print(canvas.width(), canvas.height())
canvas.mpl_connect('button_press_event', canvas.mouse_press)
canvas.mpl_connect('motion_notify_event', canvas.mouse_press)
canvas.show()
app.exec_() There are still a couple too many ad-hoc
|
|
and by size I mean looking at |
It is in resizeEvent |
xlink to #8440 |
🐉 🐲 🐉 |
@tacaswell - the fixed example you showed in #8052 (comment) does not work correctly on my MacBook Pro with retina display with the latest developer version of Matplotlib. Does it still work ok for you? |
@astrofrog The changes just got merged up to master today, they were on the 2.0.x branch. |
but it is halving the size of figure again..... |
You would think keeping track of two coordinate frames would not be so hard.... |
On a bit more consideration, I think this is working again, but there is some weird order of operations going on here starting up the window (It pulls the size to use from the un-scaled DPI and then at some point triggers a resize event which in turn down-sizes the figure (via a By a code path that is not immediantly clear to me now, going through from PyQt5 import QtGui, QtWidgets
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
# import matplotlib.pyplot as plt
# plt.ion()
class MplCanvas(FigureCanvas):
def __init__(self, fig):
FigureCanvas.__init__(self, fig)
self.renderer = None
self.x = self.y = 0
def paintEvent(self, event):
if self.renderer is None:
self.renderer = self.get_renderer()
super(MplCanvas, self).paintEvent(event)
p = QtGui.QPainter(self)
pen = QtGui.QPen(QtGui.QColor('black'))
pen.setWidth(20)
p.setPen(pen)
p.drawPoint(self.x, self.y)
def mouse_press(self, event):
# convert from data -> screen pixels -> logical pixels
x, y = ax.transData.transform((event.xdata, event.ydata)) / self._dpi_ratio
self.x, self.y = x, self.height() - y
self.update()
app = QtWidgets.QApplication([''])
# this dpi is 1/2 the dpi of my screen
fig = Figure(figsize=(6, 4), dpi=155/2)
canvas = MplCanvas(fig)
ax = fig.add_axes([0, 0, 1, 1])
print(ax.transData.transform((0.0, 0.0)))
print(ax.transData.transform((0.5, 0.5)))
print(ax.transData.transform((1.0, 1.0)))
print(canvas.width(), canvas.height())
print(fig.get_size_inches())
canvas.mpl_connect('button_press_event', canvas.mouse_press)
canvas.mpl_connect('motion_notify_event', canvas.mouse_press)
canvas.show()
fig.set_size_inches(6, 4)
canvas.resize(*canvas.get_width_height())
print(ax.transData.transform((0.0, 0.0)))
print(ax.transData.transform((0.5, 0.5)))
print(ax.transData.transform((1.0, 1.0)))
print(canvas.width(), canvas.height())
print(fig.get_size_inches())
app.exec_() I have been invoking this via
on a linux box (arch + awesomeWM + a 4k display that report
from I also have a normal dpi monitor and moving the window back-and-forth still has issues, moving it to the other monitor seems to cut the size in half the first time (but not on future times) and does not double when moving back, but the mouse events work correctly on both screens and after moving back and forth. This does not seem to happen with figures wrapped in the We need to hook up http://doc.qt.io/qt-5/qwindow.html#screenChanged and update the dpi accordingly, but I am not sure I want to hold 2.0.2 (which has a bunch of critical bug fixes) for that. This will be a pretty major bit of work as the |
IIRC, I believe it's the |
@astrofrog Is this fully addressed by #8931 |
@tacaswell - good question, I didn't think of them as the same bug but it might be fixed! Will check and report back. |
I am going to say this is taken care of, possibly super-ceded by #9062 |
I am running into issues with Matplotlib 2.0 with the Qt5 backend. The following script:
returns
with Qt5, and:
with Qt4. In Qt5 there is a factor of 4x difference between the display coordinates and the size of the widget, where I think there should only be a factor of 2x. A more visual way to see this issue is to run:
This shows a window where if you move around the cursor, a black square should follow it. With Qt5, the square is offset by a factor of 2x:
cc @tacaswell
The text was updated successfully, but these errors were encountered: