8000 Qt embedding example: Separate drawing and data retrieval timers · matplotlib/matplotlib@0f92e8c · GitHub
[go: up one dir, main page]

Skip to content

Commit 0f92e8c

Browse files
committed
Qt embedding example: Separate drawing and data retrieval timers
In the previous version of this example, if the timer interval would have been simply decreased to 1ms, the GUI could have appeared as stuck on some platforms / (slow) machines, because the event loop didn't find the time to respond to external events such as the user dragging the window etc. This change does 3 things: - Puts the data to plot in the self.{x,y}data attributes. - Separates the timer that updates the self.{x,y}data from the timer that updates the canvas - Explains much better the reasoning for the timers' intervals choices in comments, as well as explaining why the timers are attributed to self, although they are not used by other methods of the class. - Use the asynchronous draw_idle() function to further guarantee that the drawing won't be blocking.
1 parent 0da7d89 commit 0f92e8c

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

galleries/examples/user_interfaces/embedding_in_qt_sgskip.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,34 @@ def __init__(self):
4444
self._static_ax.plot(t, np.tan(t), ".")
4545

4646
self._dynamic_ax = dynamic_canvas.figure.subplots()
47-
t = np.linspace(0, 10, 101)
4847
# Set up a Line2D.
49-
self._line, = self._dynamic_ax.plot(t, np.sin(t + time.time()))
50-
self._timer = dynamic_canvas.new_timer(50)
51-
self._timer.add_callback(self._update_canvas)
52-
self._timer.start()
48+
self._update_data()
49+
self._line, = self._dynamic_ax.plot(self.xdata, self.ydata)
50+
# The below two timers must be attributes of self, so that the garbage
51+
# collector won't clean them after we finish with __init__...
5352

54-
def _update_canvas(self):
55-
t = np.linspace(0, 10, 101)
53+
# The data retrieval should be fast as possible (Using QRunnable should
54+
# be even faster)
55+
self.dataTimer = dynamic_canvas.new_timer(1)
56+
self.dataTimer.add_callback(self._update_data)
57+
self.dataTimer.start()
58+
# Drawing at 50Hz should be fast enough for the GUI to feel smooth, and
59+
# not too fast for the GUI to be overloaded with events that need to be
60+
# processed while the GUI element is changed.
61+
self.drawingTimer = dynamic_canvas.new_timer(50)
62+
self.drawingTimer.add_callback(self._update_canvas)
63+
self.drawingTimer.start()
64+
65+
def _update_data(self):
66+
self.xdata = np.linspace(0, 10, 101)
5667
# Shift the sinusoid as a function of time.
57-
self._line.set_data(t, np.sin(t + time.time()))
58-
self._line.figure.canvas.draw()
68+
self.ydata = np.sin(self.xdata + time.time())
69+
70+
def _update_canvas(self):
71+
self._line.set_data(self.xdata, self.ydata)
72+
# It should be safe to use the synchronous draw() method as well for
73+
# most drawing frequencies, but it should be safer to use draw_idle().
74+
self._line.figure.canvas.draw_idle()
5975

6076

6177
if __name__ == "__main__":

0 commit comments

Comments
 (0)
0