from gi.repository import GObject timer = None def cancel(): global timer if timer: GObject.source_remove(timer) timer = None LINEAR=1 DECELERATE=2 def animate_value(callback, current, target, policy=DECELERATE, speed=32): global timer timer = None if current != target: if policy == DECELERATE: delta = abs(target - current) / 2 else: delta = speed if current > target: current -= delta else: current += delta if abs(current - target) < 2: current = target callback(current) timer = GObject.timeout_add(1000 / 25, lambda: animate_value(callback, current, target)) def scroll_to(scrollview, widget): result = widget.translate_coordinates(scrollview.get_child().get_child(), 0, 0) if result: adj = scrollview.get_vadjustment() animate_value(adj.set_value, adj.get_value(), result[1])