From b833a2b471b257a70b2a2d33f09339ab0dc1ef09 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 13 Apr 2020 18:23:18 +0200 Subject: [PATCH] TextBox improvements. Cleanup textbox example: 1) handling the initial text through the normal `submit` callback seems simpler; 2) use "normal" autoscaling methods, which correctly apply margins and would also work if other artists were involved. This revealed that `TextBox.set_val` throws an exception due to no cached renderer if the figure has never been rendered before. Given that TextBox is going to trigger a bunch of redraws anyways for user edits, we may as well trigger a first draw if needed to cache a renderer first. --- examples/widgets/textbox.py | 18 +++++++++++------- lib/matplotlib/widgets.py | 6 ++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/examples/widgets/textbox.py b/examples/widgets/textbox.py index 96d1133686d9..8154126b6133 100644 --- a/examples/widgets/textbox.py +++ b/examples/widgets/textbox.py @@ -16,12 +16,13 @@ import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import TextBox + + fig, ax = plt.subplots() -plt.subplots_adjust(bottom=0.2) +fig.subplots_adjust(bottom=0.2) + t = np.arange(-2.0, 2.0, 0.001) -s = t ** 2 -initial_text = "t ** 2" -l, = plt.plot(t, s, lw=2) # make a plot for the math expression "t ** 2" +l, = ax.plot(t, np.zeros_like(t), lw=2) def submit(expression): @@ -33,12 +34,15 @@ def submit(expression): """ ydata = eval(expression) l.set_ydata(ydata) - ax.set_ylim(np.min(ydata), np.max(ydata)) + ax.relim() + ax.autoscale_view() plt.draw() -axbox = plt.axes([0.1, 0.05, 0.8, 0.075]) -text_box = TextBox(axbox, 'Evaluate', initial=initial_text) + +axbox = fig.add_axes([0.1, 0.05, 0.8, 0.075]) +text_box = TextBox(axbox, "Evaluate") text_box.on_submit(submit) +text_box.set_val("t ** 2") # Trigger `submit` with the initial string. plt.show() diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py index 544f8d1f1c49..be060e8763d9 100644 --- a/lib/matplotlib/widgets.py +++ b/lib/matplotlib/widgets.py @@ -767,6 +767,12 @@ def _rendercursor(self): # and save its dimensions, draw the real text, then put the cursor # at the saved dimensions + # This causes a single extra draw if the figure has never been rendered + # yet, which should be fine as we're going to repeatedly re-render the + # figure later anyways. + if self.ax.figure._cachedRenderer is None: + self.ax.figure.canvas.draw() + text = self.text_disp.get_text() # Save value before overwriting it. widthtext = text[:self.cursor_index] self.text_disp.set_text(widthtext or ",")