#!/usr/bin/env python # An example of an animation done with cairo and Gtk+ # # Copyright (C) 2013 Antonio Ospite # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # References: # http://wiki.laptop.org/go/PyGTK/Smooth_Animation_with_PyGTK import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GObject, Gio import math import colorsys class AnimatedCanvas(Gtk.DrawingArea): def __init__(self, width, height, *args, **kwargs): super(AnimatedCanvas, self).__init__(*args, **kwargs) self.width = width self.height = height self.x_offset = 2 self.y_offset = 3 self.radius = 10 self.border = 4 self.x = self.radius + self.border self.y = self.radius + self.border self.set_size_request(width, height) self.connect('draw', self.do_draw_cb) self.connect('configure-event', self.do_configure_event_cb) fps = 30 GObject.timeout_add(1000 / fps, self.update) def update(self): if self.x - self.radius - self.border < 0 or \ self.x + self.radius + self.border > self.width: self.x_offset *= -1 if self.y - self.radius - self.border < 0 or \ self.y + self.radius + self.border > self.height: self.y_offset *= -1 self.x += self.x_offset self.y += self.y_offset self.queue_draw() return True def do_configure_event_cb(self, widget, event): self.width = event.width self.height = event.height def do_draw_cb(self, widget, cr): cr.rectangle(0, 0, self.width, self.height) cr.set_source_rgb(1.0, 0.5, 0.5) cr.fill() cr.arc(self.x, self.y, self.radius, 0, 2 * math.pi) cr.set_line_width(self.border) _h = self.x / float(self.width) _l = 0.5 _s = self.y / float(self.height) _r, _g, _b = colorsys.hls_to_rgb(_h, _l, _s) cr.set_source_rgb(_r, _g, _b) cr.fill_preserve() cr.set_source_rgb(0, 0, 0) cr.stroke() class AnimatedApp(Gtk.Application): def __init__(self, title, width, height, *args, **kwargs): super(AnimatedApp, self).__init__(*args, **kwargs) self.connect("activate", self.on_activate) self.title = title self.width = width self.height = height def on_activate(self, data=None): window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL) window.set_title(self.title) canvas = AnimatedCanvas(self.width, self.height) window.add(canvas) window.show_all() self.add_window(window) if __name__ == "__main__": app = AnimatedApp( "AnimatedApp", 640, 480, application_id="apps.test.animatedapp", flags=Gio.ApplicationFlags.FLAGS_NONE) app.run(None)