Skip to content

Commit b975b75

Browse files
authored
Merge pull request #17877 from QuLogic/gtk3-rubberband
Fix drawing zoom rubberband on GTK backends.
2 parents 660f931 + 508350a commit b975b75

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

doc/users/prev_whats_new/whats_new_3.3.0.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,8 @@ Previously, the x/y position displayed by the cursor text would usually include
612612
far more significant digits than the mouse pointing precision (typically one
613613
pixel). This is now fixed for linear scales.
614614

615-
Qt zoom rectangle now black and white
616-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
615+
GTK / Qt zoom rectangle now black and white
616+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
617617

618618
This makes it visible even over a dark background.
619619

lib/matplotlib/backends/backend_gtk3.py

+44-16
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,14 @@ def __init__(self, figure):
159159

160160
self._idle_draw_id = 0
161161
self._lastCursor = None
162+
self._rubberband_rect = None
162163

163164
self.connect('scroll_event', self.scroll_event)
164165
self.connect('button_press_event', self.button_press_event)
165166
self.connect('button_release_event', self.button_release_event)
166167
self.connect('configure_event', self.configure_event)
167168
self.connect('draw', self.on_draw_event)
169+
self.connect('draw', self._post_draw)
168170
self.connect('key_press_event', self.key_press_event)
169171
self.connect('key_release_event', self.key_release_event)
170172
self.connect('motion_notify_event', self.motion_notify_event)
@@ -286,6 +288,40 @@ def configure_event(self, widget, event):
286288
self.figure.set_size_inches(w / dpi, h / dpi, forward=False)
287289
return False # finish event propagation?
288290

291+
def _draw_rubberband(self, rect):
292+
self._rubberband_rect = rect
293+
# TODO: Only update the rubberband area.
294+
self.queue_draw()
295+
296+
def _post_draw(self, widget, ctx):
297+
if self._rubberband_rect is None:
298+
return
299+
300+
x0, y0, w, h = self._rubberband_rect
301+
x1 = x0 + w
302+
y1 = y0 + h
303+
304+
# Draw the lines from x0, y0 towards x1, y1 so that the
305+
# dashes don't "jump" when moving the zoom box.
306+
ctx.move_to(x0, y0)
307+
ctx.line_to(x0, y1)
308+
ctx.move_to(x0, y0)
309+
ctx.line_to(x1, y0)
310+
ctx.move_to(x0, y1)
311+
ctx.line_to(x1, y1)
312+
ctx.move_to(x1, y0)
313+
ctx.line_to(x1, y1)
314+
315+
ctx.set_antialias(1)
316+
ctx.set_line_width(1)
317+
ctx.set_dash((3, 3), 0)
318+
ctx.set_source_rgb(0, 0, 0)
319+
ctx.stroke_preserve()
320+
321+
ctx.set_dash((3, 3), 3)
322+
ctx.set_source_rgb(1, 1, 1)
323+
ctx.stroke()
324+
289325
def on_draw_event(self, widget, ctx):
290326
# to be overwritten by GTK3Agg or GTK3Cairo
291327
pass
@@ -507,26 +543,14 @@ def set_cursor(self, cursor):
507543
Gtk.main_iteration()
508544

509545
def draw_rubberband(self, event, x0, y0, x1, y1):
510-
# adapted from
511-
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/189744
512-
ctx = self.canvas.get_property("window").cairo_create()
513-
514-
# todo: instead of redrawing the entire figure, copy the part of
515-
# the figure that was covered by the previous rubberband rectangle
516-
self.canvas.draw()
517-
518546
height = self.canvas.figure.bbox.height
519547
y1 = height - y1
520548
y0 = height - y0
521-
w = abs(x1 - x0)
522-
h = abs(y1 - y0)
523-
rect = [int(val) for val in (min(x0, x1), min(y0, y1), w, h)]
549+
rect = [int(val) for val in (x0, y0, x1 - x0, y1 - y0)]
550+
self.canvas._draw_rubberband(rect)
524551

525-
ctx.new_path()
526-
ctx.set_line_width(0.5)
527-
ctx.rectangle(rect[0], rect[1], rect[2], rect[3])
528-
ctx.set_source_rgb(0, 0, 0)
529-
ctx.stroke()
552+
def remove_rubberband(self):
553+
self.canvas._draw_rubberband(None)
530554

531555
def _update_buttons_checked(self):
532556
for name, active in [("Pan", "PAN"), ("Zoom", "ZOOM")]:
@@ -721,6 +745,10 @@ def draw_rubberband(self, x0, y0, x1, y1):
721745
NavigationToolbar2GTK3.draw_rubberband(
722746
self._make_classic_style_pseudo_toolbar(), None, x0, y0, x1, y1)
723747

748+
def remove_rubberband(self):
749+
NavigationToolbar2GTK3.remove_rubberband(
750+
self._make_classic_style_pseudo_toolbar())
751+
724752

725753
class SaveFigureGTK3(backend_tools.SaveFigureBase):
726754
def trigger(self, *args, **kwargs):

0 commit comments

Comments
 (0)