CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pytermgui

Python TUI framework with mouse support, modular widget system, customizable and rapid terminal markup language and more

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

animations.mddocs/

Animations

PyTermGUI's animation system provides smooth property transitions and dynamic effects for creating engaging user interfaces. The system supports value animations, attribute animations, and custom easing functions.

Capabilities

Animator

Central animation manager that schedules and executes animations with timing control and coordination.

class Animator:
    """Animation management system."""
    
    def __init__(self):
        """Initialize animator."""
    
    def schedule(self, animation):
        """
        Schedule animation for execution.
        
        Parameters:
        - animation: Animation instance to schedule
        """
    
    def run(self):
        """Run animation loop until all animations complete."""
    
    def stop(self):
        """Stop all animations."""
    
    def update(self, delta_time: float):
        """Update all animations by time delta."""
    
    @property
    def is_running(self) -> bool:
        """Check if any animations are active."""
    
    def clear(self):
        """Clear all scheduled animations."""

# Global animator instance
animator: Animator

Float Animation

Numeric value animation with configurable easing and duration.

class FloatAnimation:
    """Floating-point value animation."""
    
    def __init__(self, duration: float, start: float, end: float, 
                 easing: str = "linear"):
        """
        Create float animation.
        
        Parameters:
        - duration (float): Animation duration in seconds
        - start (float): Starting value
        - end (float): Ending value
        - easing (str): Easing function name
        """
    
    @property
    def value(self) -> float:
        """Get current animated value."""
    
    @property
    def progress(self) -> float:
        """Get animation progress (0.0 to 1.0)."""
    
    @property
    def is_finished(self) -> bool:
        """Check if animation is complete."""
    
    def set_callback(self, callback: Callable[[float], None]):
        """Set callback function called with each value update."""

Attribute Animation

Object attribute animation for animating widget properties.

class AttrAnimation:
    """Object attribute animation."""
    
    def __init__(self, obj: object, attr: str, duration: float, 
                 end_value: float, easing: str = "linear"):
        """
        Create attribute animation.
        
        Parameters:
        - obj: Target object to animate
        - attr (str): Attribute name to animate
        - duration (float): Animation duration in seconds
        - end_value: Target value for attribute
        - easing (str): Easing function name
        """
    
    @property
    def current_value(self) -> float:
        """Get current attribute value."""
    
    @property
    def is_finished(self) -> bool:
        """Check if animation is complete."""

Animation Utilities

Helper functions for animation management and detection.

def is_animated(target: object, attribute: str) -> bool:
    """
    Check if object attribute is animated.
    
    Parameters:
    - target: Object to check
    - attribute (str): Attribute name to check
    
    Returns:
    True if the specified attribute is animated
    """

Easing Functions

Built-in easing functions for natural animation curves.

# Available easing function names:
EASING_FUNCTIONS = [
    "linear",
    "ease_in",
    "ease_out", 
    "ease_in_out",
    "bounce_in",
    "bounce_out",
    "elastic_in",
    "elastic_out"
]

Usage Examples

Basic Value Animation

import pytermgui as ptg
import time

# Create a simple float animation
animation = ptg.FloatAnimation(
    duration=2.0,
    start=0.0,
    end=100.0,
    easing="ease_in_out"
)

# Set callback to handle value updates
def on_value_change(value):
    print(f"Current value: {value:.2f}")

animation.set_callback(on_value_change)

# Schedule and run animation
ptg.animator.schedule(animation)
ptg.animator.run()

Widget Property Animation

import pytermgui as ptg

# Create widget and animate its width
container = ptg.Container(width=20, height=10)

# Animate width from 20 to 60 over 1.5 seconds
width_animation = ptg.AttrAnimation(
    obj=container,
    attr="width", 
    duration=1.5,
    end_value=60,
    easing="bounce_out"
)

ptg.animator.schedule(width_animation)
ptg.animator.run()

Multiple Animations

import pytermgui as ptg

# Create widget
window = ptg.Window("Animated Window", width=40, height=15)

# Create multiple animations
animations = [
    ptg.AttrAnimation(window, "width", 2.0, 80, "ease_out"),
    ptg.AttrAnimation(window, "height", 1.5, 25, "ease_in"),
]

# Schedule all animations
for animation in animations:
    ptg.animator.schedule(animation)

# Run animations concurrently
ptg.animator.run()

Color Animation

import pytermgui as ptg

# Animate color transitions
class ColorAnimation:
    def __init__(self, widget, duration, start_color, end_color):
        self.widget = widget
        self.start_rgb = start_color.rgb
        self.end_rgb = end_color.rgb
        
        # Create component animations
        self.r_anim = ptg.FloatAnimation(duration, self.start_rgb[0], self.end_rgb[0])
        self.g_anim = ptg.FloatAnimation(duration, self.start_rgb[1], self.end_rgb[1])  
        self.b_anim = ptg.FloatAnimation(duration, self.start_rgb[2], self.end_rgb[2])
        
        # Set update callback
        self.r_anim.set_callback(self.update_color)
        
    def update_color(self, _):
        r = int(self.r_anim.value)
        g = int(self.g_anim.value)
        b = int(self.b_anim.value)
        new_color = ptg.RGBColor(r, g, b)
        # Update widget color property
        self.widget.styles.border = str(new_color)

# Usage
label = ptg.Label("Animated Text")
color_anim = ColorAnimation(
    label, 
    duration=3.0,
    start_color=ptg.Color("red"),
    end_color=ptg.Color("blue")
)

ptg.animator.schedule(color_anim.r_anim)
ptg.animator.schedule(color_anim.g_anim)
ptg.animator.schedule(color_anim.b_anim)
ptg.animator.run()

Chained Animations

import pytermgui as ptg

def create_sequence():
    """Create sequence of chained animations."""
    button = ptg.Button("Animated Button")
    
    def phase1_done():
        # Start second animation when first completes
        phase2 = ptg.AttrAnimation(button, "width", 1.0, 20, "bounce_in")
        phase2.set_callback(lambda _: print("Animation complete!"))
        ptg.animator.schedule(phase2)
    
    # First animation
    phase1 = ptg.AttrAnimation(button, "height", 1.0, 5, "ease_out")
    phase1.set_callback(lambda _: phase1_done() if phase1.is_finished else None)
    
    ptg.animator.schedule(phase1)
    return button

# Create and run sequence
animated_button = create_sequence()
ptg.animator.run()

Animation in Window Manager

import pytermgui as ptg

def animate_window_entrance(window):
    """Animate window appearing."""
    # Start window small and grow it
    window.width = 10
    window.height = 5
    
    # Animate to full size
    width_anim = ptg.AttrAnimation(window, "width", 0.8, 60, "bounce_out")
    height_anim = ptg.AttrAnimation(window, "height", 0.6, 20, "ease_out")
    
    ptg.animator.schedule(width_anim)
    ptg.animator.schedule(height_anim)

with ptg.WindowManager() as manager:
    window = ptg.Window(
        "[bold]Welcome!",
        "",
        ptg.Label("This window animated in"),
        ptg.Button("Close", lambda btn: manager.stop()),
        title="Animated Window"
    )
    
    manager.add(window)
    animate_window_entrance(window)
    
    # Run animations alongside window manager
    import threading
    animation_thread = threading.Thread(target=ptg.animator.run)
    animation_thread.start()

Custom Animation Callback

import pytermgui as ptg

class PulsingLabel(ptg.Label):
    """Label that pulses with animation."""
    
    def __init__(self, text, **attrs):
        super().__init__(text, **attrs)
        self.start_pulsing()
    
    def start_pulsing(self):
        """Start pulsing animation."""
        def pulse_callback(value):
            # Use animation value to control text brightness
            intensity = int(value)
            self.value = f"[{intensity}]{self.original_text}[/{intensity}]"
        
        self.original_text = self.value
        
        # Create pulsing animation (back and forth)
        pulse_out = ptg.FloatAnimation(1.0, 210, 240, "ease_in_out")
        pulse_out.set_callback(pulse_callback)
        
        def restart_animation():
            if pulse_out.is_finished:
                # Restart the pulse
                new_pulse = ptg.FloatAnimation(1.0, 240, 210, "ease_in_out")
                new_pulse.set_callback(pulse_callback)
                ptg.animator.schedule(new_pulse)
        
        pulse_out.set_callback(lambda v: (pulse_callback(v), restart_animation()))
        ptg.animator.schedule(pulse_out)

# Usage
pulsing_label = PulsingLabel("This text pulses!")
ptg.animator.run()

Install with Tessl CLI

npx tessl i tessl/pypi-pytermgui

docs

animations.md

colors-markup.md

file-loading.md

index.md

terminal.md

utilities.md

widgets.md

window-management.md

tile.json