Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Timers independent of canvases #1907

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

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/event_handling/timers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Simple example of using general timer objects. This is used to update
# the time placed in the title of the figure.
import matplotlib.pyplot as plt
from matplotlib import events
import numpy as np
from datetime import datetime

Expand All @@ -16,7 +17,7 @@ def update_title(axes):

# Create a new timer object. Set the interval 500 milliseconds (1000 is default)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is different from what is implemented

# and tell the timer what function should be called.
timer = fig.canvas.new_timer(interval=100)
timer = events.Timer(interval=100)
timer.add_callback(update_title, ax)
timer.start()

Expand Down
4 changes: 3 additions & 1 deletion lib/matplotlib/animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from matplotlib.compat import subprocess
from matplotlib import verbose
from matplotlib import rcParams
from matplotlib import events


# Other potential writing methods:
# * http://pymedia.org/
Expand Down Expand Up @@ -845,7 +847,7 @@ def __init__(self, fig, interval=200, repeat_delay=None, repeat=True,
# If we're not given an event source, create a new timer. This permits
# sharing timers between animation objects for syncing animations.
if event_source is None:
event_source = fig.canvas.new_timer()
event_source = events.Timer()
event_source.interval = self._interval

Animation.__init__(self, fig, event_source=event_source,
Expand Down
20 changes: 0 additions & 20 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -1049,9 +1049,6 @@ def __init__(self, interval=None, callbacks=None):

self._single = False

# Default attribute for holding the GUI-specific timer object
self._timer = None

def __del__(self):
'Need to stop timer and possibly disconnect timer.'
self._timer_stop()
Expand Down Expand Up @@ -2258,23 +2255,6 @@ def mpl_disconnect(self, cid):
"""
return self.callbacks.disconnect(cid)

def new_timer(self, *args, **kwargs):
"""
Creates a new backend-specific subclass of
:class:`backend_bases.Timer`. This is useful for getting periodic
events through the backend's native event loop. Implemented only for
backends with GUIs.

optional arguments:

*interval*
Timer interval in milliseconds
*callbacks*
Sequence of (func, args, kwargs) where func(*args, **kwargs) will
be executed by the timer every *interval*.
"""
return TimerBase(*args, **kwargs)

def flush_events(self):
"""
Flush the GUI events for the figure. Implemented only for
Expand Down
36 changes: 7 additions & 29 deletions lib/matplotlib/backends/backend_gtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,13 @@ def new_figure_manager_given_figure(num, figure):
return manager


class TimerGTK(TimerBase):
'''
Subclass of :class:`backend_bases.TimerBase` that uses GTK for timer events.

Attributes:
* interval: The time between timer events in milliseconds. Default
is 1000 ms.
* single_shot: Boolean flag indicating whether this timer should
operate as single shot (run once and then stop). Defaults to False.
* callbacks: Stores list of (func, args) tuples that will be called
upon timer events. This list can be manipulated directly, or the
functions add_callback and remove_callback can be used.
'''
class Timer(TimerBase):
__doc__ = TimerBase.__doc__

def __init__(self, *args, **kwargs):
TimerBase.__init__(self, *args, **kwargs)
self._timer = None

def _timer_start(self):
# Need to stop it, otherwise we potentially leak a timer id that will
# never be stopped.
Expand Down Expand Up @@ -487,22 +481,6 @@ def save_callback(buf, data=None):
else:
raise ValueError("filename must be a path or a file-like object")

def new_timer(self, *args, **kwargs):
"""
Creates a new backend-specific subclass of :class:`backend_bases.Timer`.
This is useful for getting periodic events through the backend's native
event loop. Implemented only for backends with GUIs.

optional arguments:

*interval*
Timer interval in milliseconds
*callbacks*
Sequence of (func, args, kwargs) where func(*args, **kwargs) will
be executed by the timer every *interval*.
"""
return TimerGTK(*args, **kwargs)

def flush_events(self):
gtk.gdk.threads_enter()
while gtk.events_pending():
Expand Down
36 changes: 7 additions & 29 deletions lib/matplotlib/backends/backend_gtk3.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,13 @@ def mainloop(self):
show = Show()


class TimerGTK3(TimerBase):
'''
Subclass of :class:`backend_bases.TimerBase` that uses GTK3 for timer events.

Attributes:
* interval: The time between timer events in milliseconds. Default
is 1000 ms.
* single_shot: Boolean flag indicating whether this timer should
operate as single shot (run once and then stop). Defaults to False.
* callbacks: Stores list of (func, args) tuples that will be called
upon timer events. This list can be manipulated directly, or the
functions add_callback and remove_callback can be used.
'''
class Timer(TimerBase):
__doc__ = TimerBase.__doc__

def __init__(self, *args, **kwargs):
TimerBase.__init__(self, *args, **kwargs)
self._timer = None

def _timer_start(self):
# Need to stop it, otherwise we potentially leak a timer id that will
# never be stopped.
Expand Down Expand Up @@ -310,22 +304,6 @@ def idle_draw(*args):
if self._idle_draw_id == 0:
self._idle_draw_id = GObject.idle_add(idle_draw)

def new_timer(self, *args, **kwargs):
"""
Creates a new backend-specific subclass of :class:`backend_bases.Timer`.
This is useful for getting periodic events through the backend's native
event loop. Implemented only for backends with GUIs.

optional arguments:

*interval*
Timer interval in milliseconds
*callbacks*
Sequence of (func, args, kwargs) where func(*args, **kwargs) will
be executed by the timer every *interval*.
"""
return TimerGTK3(*args, **kwargs)

def flush_events(self):
Gdk.threads_enter()
while Gtk.events_pending():
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/backends/backend_gtk3agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,4 @@ def new_figure_manager_given_figure(num, figure):

FigureManager = FigureManagerGTK3Agg
show = backend_gtk3.show
Timer = backend_gtk3.Timer
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_gtkagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from matplotlib.backends.backend_gtk import gtk, FigureManagerGTK, FigureCanvasGTK,\
show, draw_if_interactive,\
error_msg_gtk, NavigationToolbar, PIXELS_PER_INCH, backend_version, \
NavigationToolbar2GTK
NavigationToolbar2GTK, Timer
from matplotlib.backends._gtkagg import agg_to_gtk_drawable


Expand Down
32 changes: 2 additions & 30 deletions lib/matplotlib/backends/backend_macosx.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,20 +245,8 @@ def new_figure_manager_given_figure(num, figure):
return manager


class TimerMac(_macosx.Timer, TimerBase):
'''
Subclass of :class:`backend_bases.TimerBase` that uses CoreFoundation
run loops for timer events.

Attributes:
* interval: The time between timer events in milliseconds. Default
is 1000 ms.
* single_shot: Boolean flag indicating whether this timer should
operate as single shot (run once and then stop). Defaults to False.
* callbacks: Stores list of (func, args) tuples that will be called
upon timer events. This list can be manipulated directly, or the
functions add_callback and remove_callback can be used.
'''
class Timer(_macosx.Timer, TimerBase):
__doc__ = TimerBase.__doc__
# completely implemented at the C-level (in _macosx.Timer)


Expand Down Expand Up @@ -329,22 +317,6 @@ def print_tiff(self, filename, *args, **kwargs):
def print_gif(self, filename, *args, **kwargs):
self._print_bitmap(filename, *args, **kwargs)

def new_timer(self, *args, **kwargs):
"""
Creates a new backend-specific subclass of :class:`backend_bases.Timer`.
This is useful for getting periodic events through the backend's native
event loop. Implemented only for backends with GUIs.

optional arguments:

*interval*
Timer interval in milliseconds
*callbacks*
Sequence of (func, args, kwargs) where func(*args, **kwargs) will
be executed by the timer every *interval*.
"""
return TimerMac(*args, **kwargs)


class FigureManagerMac(_macosx.FigureManager, FigureManagerBase):
"""
Expand Down
48 changes: 10 additions & 38 deletions lib/matplotlib/backends/backend_qt4.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,50 +85,38 @@ def new_figure_manager_given_figure(num, figure):
return manager


class TimerQT(TimerBase):
'''
Subclass of :class:`backend_bases.TimerBase` that uses Qt4 timer events.

Attributes:
* interval: The time between timer events in milliseconds. Default
is 1000 ms.
* single_shot: Boolean flag indicating whether this timer should
operate as single shot (run once and then stop). Defaults to False.
* callbacks: Stores list of (func, args) tuples that will be called
upon timer events. This list can be manipulated directly, or the
functions add_callback and remove_callback can be used.
'''
class Timer(TimerBase, QtCore.QTimer):
__doc__ = TimerBase.__doc__

def __init__(self, *args, **kwargs):
TimerBase.__init__(self, *args, **kwargs)

# Create a new timer and connect the timeout() signal to the
# _on_timer method.
self._timer = QtCore.QTimer()
QtCore.QObject.connect(self._timer, QtCore.SIGNAL('timeout()'),
self._on_timer)
QtCore.QTimer.__init__(self)
self.timeout.connect(self._on_timer)
self._timer_set_interval()

def __del__(self):
# Probably not necessary in practice, but is good behavior to disconnect
try:
TimerBase.__del__(self)
QtCore.QObject.disconnect(self._timer,
QtCore.SIGNAL('timeout()'), self._on_timer)
self.timeout.disconnect(self._on_timer)
except RuntimeError:
# Timer C++ object already deleted
pass

def _timer_set_single_shot(self):
self._timer.setSingleShot(self._single)
self.setSingleShot(self._single)

def _timer_set_interval(self):
self._timer.setInterval(self._interval)
self.setInterval(self._interval)

def _timer_start(self):
self._timer.start()
QtCore.QTimer.start(self)

def _timer_stop(self):
self._timer.stop()
QtCore.QTimer.stop(self)


class FigureCanvasQT( QtGui.QWidget, FigureCanvasBase ):
Expand Down Expand Up @@ -331,22 +319,6 @@ def _get_key( self, event ):

return key

def new_timer(self, *args, **kwargs):
"""
Creates a new backend-specific subclass of :class:`backend_bases.Timer`.
This is useful for getting periodic events through the backend's native
event loop. Implemented only for backends with GUIs.

optional arguments:

*interval*
Timer interval in milliseconds
*callbacks*
Sequence of (func, args, kwargs) where func(*args, **kwargs) will
be executed by the timer every *interval*.
"""
return TimerQT(*args, **kwargs)

def flush_events(self):
QtGui.qApp.processEvents()

Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_qt4agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from backend_agg import FigureCanvasAgg
from backend_qt4 import QtCore, QtGui, FigureManagerQT, FigureCanvasQT,\
show, draw_if_interactive, backend_version, \
NavigationToolbar2QT
NavigationToolbar2QT, Timer

DEBUG = False

Expand Down
42 changes: 8 additions & 34 deletions lib/matplotlib/backends/backend_tkagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,31 +110,21 @@ def new_figure_manager_given_figure(num, figure):
return figManager


class TimerTk(TimerBase):
'''
Subclass of :class:`backend_bases.TimerBase` that uses Tk's timer events.

Attributes:
* interval: The time between timer events in milliseconds. Default
is 1000 ms.
* single_shot: Boolean flag indicating whether this timer should
operate as single shot (run once and then stop). Defaults to False.
* callbacks: Stores list of (func, args) tuples that will be called
upon timer events. This list can be manipulated directly, or the
functions add_callback and remove_callback can be used.
'''
def __init__(self, parent, *args, **kwargs):
class Timer(TimerBase):
__doc__ = TimerBase.__doc__

def __init__(self, *args, **kwargs):
TimerBase.__init__(self, *args, **kwargs)
self.parent = parent
self._timer = None
self._tcl = Tk.Tcl()

def _timer_start(self):
self._timer_stop()
self._timer = self.parent.after(self._interval, self._on_timer)
self._timer = self._tcl.after(self._interval, self._on_timer)

def _timer_stop(self):
if self._timer is not None:
self.parent.after_cancel(self._timer)
self._tcl.after_cancel(self._timer)
self._timer = None

def _on_timer(self):
Expand All @@ -143,7 +133,7 @@ def _on_timer(self):
# Tk after() is only a single shot, so we need to add code here to
# reset the timer if we're not operating in single shot mode.
if not self._single and len(self.callbacks) > 0:
self._timer = self.parent.after(self._interval, self._on_timer)
self._timer = self._tcl.after(self._interval, self._on_timer)
else:
self._timer = None

Expand Down Expand Up @@ -479,22 +469,6 @@ def key_release(self, event):
key = self._get_key(event)
FigureCanvasBase.key_release_event(self, key, guiEvent=event)

def new_timer(self, *args, **kwargs):
"""
Creates a new backend-specific subclass of :class:`backend_bases.Timer`.
This is useful for getting periodic events through the backend's native
event loop. Implemented only for backends with GUIs.

optional arguments:

*interval*
Timer interval in milliseconds
*callbacks*
Sequence of (func, args, kwargs) where func(*args, **kwargs) will
be executed by the timer every *interval*.
"""
return TimerTk(self._tkcanvas, *args, **kwargs)

def flush_events(self):
self._master.update()

Expand Down
Loading