From 6392c2bc19d3d05cf4eacb17d6605679fb542b52 Mon Sep 17 00:00:00 2001 From: "Albert Y. Shih" Date: Sat, 11 Jul 2026 00:27:01 -0400 Subject: [PATCH] Round figure height in backends --- lib/matplotlib/backends/_backend_gtk.py | 2 +- lib/matplotlib/backends/_backend_tk.py | 8 ++++---- lib/matplotlib/backends/backend_gtk3.py | 2 +- lib/matplotlib/backends/backend_gtk4.py | 2 +- lib/matplotlib/backends/backend_qt.py | 4 ++-- lib/matplotlib/backends/backend_tkcairo.py | 4 ++-- lib/matplotlib/backends/backend_wx.py | 6 +++--- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/matplotlib/backends/_backend_gtk.py b/lib/matplotlib/backends/_backend_gtk.py index 0491db40e565..f88c1efebf0e 100644 --- a/lib/matplotlib/backends/_backend_gtk.py +++ b/lib/matplotlib/backends/_backend_gtk.py @@ -275,7 +275,7 @@ def set_message(self, s): self.message.set_markup(f'{escaped}') def draw_rubberband(self, event, x0, y0, x1, y1): - height = self.canvas.figure.bbox.height + height = int(self.canvas.figure.bbox.height + 0.5) y1 = height - y1 y0 = height - y0 rect = [int(val) for val in (x0, y0, x1 - x0, y1 - y0)] diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index a18a9bd8660f..cd3c63de4120 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -329,7 +329,7 @@ def _event_mpl_coords(self, event): # the top of the widget may have been scrolled out of view). return (self._tkcanvas.canvasx(event.x), # flipy so y=0 is bottom of canvas - self.figure.bbox.height - self._tkcanvas.canvasy(event.y)) + int(self.figure.bbox.height + 0.5) - self._tkcanvas.canvasy(event.y)) def motion_notify_event(self, event): MouseEvent("motion_notify_event", self, @@ -389,7 +389,7 @@ def scroll_event_windows(self, event): if w != self._tkcanvas: return x = self._tkcanvas.canvasx(event.x_root - w.winfo_rootx()) - y = (self.figure.bbox.height + y = (int(self.figure.bbox.height + 0.5) - self._tkcanvas.canvasy(event.y_root - w.winfo_rooty())) step = event.delta / 120 MouseEvent("scroll_event", self, @@ -676,7 +676,7 @@ def __init__(self, canvas, window=None, *, pack_toolbar=True): if window is None: window = canvas.get_tk_widget().master tk.Frame.__init__(self, master=window, borderwidth=2, - width=int(canvas.figure.bbox.width), height=50) + width=int(canvas.figure.bbox.width + 0.5), height=50) # Avoid message_label expanding the toolbar size, and in turn expanding the # canvas size. # Without pack_propagate(False), when the user defines a small figure size @@ -774,7 +774,7 @@ def draw_rubberband(self, event, x0, y0, x1, y1): self.canvas._tkcanvas.delete(self.canvas._rubberband_rect_white) if self.canvas._rubberband_rect_black: self.canvas._tkcanvas.delete(self.canvas._rubberband_rect_black) - height = self.canvas.figure.bbox.height + height = int(self.canvas.figure.bbox.height + 0.5) y0 = height - y0 y1 = height - y1 self.canvas._rubberband_rect_black = ( diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py index 20a1a3c8f0a9..c67c580d651f 100644 --- a/lib/matplotlib/backends/backend_gtk3.py +++ b/lib/matplotlib/backends/backend_gtk3.py @@ -119,7 +119,7 @@ def _mpl_coords(self, event=None): x, y = event.x, event.y x = x * self.device_pixel_ratio # flip y so y=0 is bottom of canvas - y = self.figure.bbox.height - y * self.device_pixel_ratio + y = int(self.figure.bbox.height + 0.5) - y * self.device_pixel_ratio return x, y def scroll_event(self, widget, event): diff --git a/lib/matplotlib/backends/backend_gtk4.py b/lib/matplotlib/backends/backend_gtk4.py index 95b116e9a6ba..1691882a670d 100644 --- a/lib/matplotlib/backends/backend_gtk4.py +++ b/lib/matplotlib/backends/backend_gtk4.py @@ -117,7 +117,7 @@ def _mpl_coords(self, xy=None): x, y = xy x = x * self.device_pixel_ratio # flip y so y=0 is bottom of canvas - y = self.figure.bbox.height - y * self.device_pixel_ratio + y = int(self.figure.bbox.height + 0.5) - y * self.device_pixel_ratio return x, y def scroll_event(self, controller, dx, dy): diff --git a/lib/matplotlib/backends/backend_qt.py b/lib/matplotlib/backends/backend_qt.py index 39450ee32065..588681fc27eb 100644 --- a/lib/matplotlib/backends/backend_qt.py +++ b/lib/matplotlib/backends/backend_qt.py @@ -305,7 +305,7 @@ def mouseEventCoords(self, pos=None): # (otherwise, it's already a QPoint) x = pos.x() # flip y so y=0 is bottom of canvas - y = self.figure.bbox.height / self.device_pixel_ratio - pos.y() + y = int(self.figure.bbox.height + 0.5) / self.device_pixel_ratio - pos.y() return x * self.device_pixel_ratio, y * self.device_pixel_ratio def enterEvent(self, event): @@ -918,7 +918,7 @@ def set_message(self, s): self.locLabel.setText(s) def draw_rubberband(self, event, x0, y0, x1, y1): - height = self.canvas.figure.bbox.height + height = int(self.canvas.figure.bbox.height + 0.5) y1 = height - y1 y0 = height - y0 rect = [int(val) for val in (x0, y0, x1 - x0, y1 - y0)] diff --git a/lib/matplotlib/backends/backend_tkcairo.py b/lib/matplotlib/backends/backend_tkcairo.py index a6951c03c65a..eac6d64b0540 100644 --- a/lib/matplotlib/backends/backend_tkcairo.py +++ b/lib/matplotlib/backends/backend_tkcairo.py @@ -9,8 +9,8 @@ class FigureCanvasTkCairo(FigureCanvasCairo, FigureCanvasTk): def draw(self): - width = int(self.figure.bbox.width) - height = int(self.figure.bbox.height) + width = int(self.figure.bbox.width + 0.5) + height = int(self.figure.bbox.height + 0.5) surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) self._renderer.set_context(cairo.Context(surface)) self._renderer.dpi = self.figure.dpi diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index 930a944b5274..6adec9d8aa8f 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -746,9 +746,9 @@ def _mpl_coords(self, pos=None): # flip y so y=0 is bottom of canvas if not wx.Platform == '__WXMSW__': scale = self.GetDPIScaleFactor() - return x*scale, self.figure.bbox.height - y*scale + return x*scale, int(self.figure.bbox.height + 0.5) - y*scale else: - return x, self.figure.bbox.height - y + return x, int(self.figure.bbox.height + 0.5) - y def _on_key_down(self, event): """Capture key press.""" @@ -1169,7 +1169,7 @@ def save_figure(self, *args): dialog.Destroy() def draw_rubberband(self, event, x0, y0, x1, y1): - height = self.canvas.figure.bbox.height + height = int(self.canvas.figure.bbox.height + 0.5) sf = 1 if wx.Platform == '__WXMSW__' else self.canvas.GetDPIScaleFactor() self.canvas._rubberband_rect = (x0/sf, (height - y0)/sf, x1/sf, (height - y1)/sf)