Basic Concepts¶
Understanding these core concepts will help you use window-art effectively.
The Desktop Singleton¶
window-art uses a singleton pattern for managing the SDL2 subsystem and all windows. The Desktop class handles:
- SDL2 initialization
- Event loop processing
- Window tracking
- Timing and frame management
You rarely interact with it directly. Instead, use the module-level functions:
import window_art as wa
# These all delegate to Desktop.get()
wa.init() # Initialize SDL2
wa.window(...) # Create a window
wa.update() # Process one frame
wa.quit() # Clean up
Auto-Initialization¶
The first call to wa.window() automatically initializes SDL2 if needed:
import window_art as wa
# No explicit init() needed
win = wa.window(100, 100, 200, 200) # Auto-initializes
The run() Context Manager¶
The recommended way to use window-art:
import window_art as wa
with wa.run():
# SDL2 initialized, windows can be created
win = wa.window(100, 100, 200, 200)
wa.wait(1)
# Automatic cleanup when exiting the context
Immediate-Mode Animation¶
Animation functions like move(), fade(), and resize() are blocking. They run to completion before returning:
import window_art as wa
with wa.run():
win = wa.window(100, 100, 100, 100)
wa.move(win, 500, 100, duration=1.0) # Blocks for 1 second
wa.move(win, 100, 100, duration=1.0) # Then blocks for another second
# Total time: 2 seconds
This makes animations predictable and easy to reason about.
Non-Blocking Alternatives¶
For advanced use cases, _async variants return generators:
import window_art as wa
with wa.run():
win = wa.window(100, 100, 100, 100)
# Get animation generator
anim = wa.move_async(win, 500, 100, duration=1.0)
# Run it manually
wa.run_animation(anim)
The Update Loop¶
The update() function processes one frame:
- Handles SDL events (window, keyboard, mouse)
- Updates animation state
- Applies pending changes to windows
- Returns
Falseif quit was requested
import window_art as wa
wa.init()
win = wa.window(100, 100, 100, 100)
while wa.update():
# Custom per-frame logic
win.x += 1
wa.quit()
Frame Timing¶
Access timing information via:
Window Properties¶
Windows have many readable and writable properties:
win = wa.window(100, 100, 200, 200, color="red")
# Position
win.x = 150
win.y = 200
win.position = (150, 200) # Set both at once
# Size
win.w = 300
win.h = 250
win.size = (300, 250) # Set both at once
# Appearance
win.color = "blue"
win.opacity = 0.8
win.title = "My Window"
# Behavior
win.borderless = False
win.always_on_top = True
win.resizable = True
win.shadow = False # macOS only
Dirty Flag Optimization¶
Property changes are batched internally. When you set win.x and win.y separately, the actual SDL calls happen together in the next update():
# These don't cause two separate window moves
win.x = 100
win.y = 200
# Both applied in next update()
This reduces WindowServer overhead significantly.
Color System¶
Colors can be specified in multiple ways:
# CSS named colors (147 supported)
win.color = "coral"
win.color = "dodgerblue"
# Hex codes
win.color = "#ff6347"
win.color = "#f00" # Short form
# RGB tuples
win.color = (255, 99, 71)
# RGBA tuples
win.color = (255, 99, 71, 128)
# Color objects
from window_art import Color
win.color = Color(255, 99, 71)
See Colors Guide for the full list of named colors.
Coordinate System¶
Coordinates use screen pixels with origin at the top-left of the primary display:
Multiple monitors extend this coordinate space. Use wa.screens() to query monitor geometry:
for screen in wa.screens():
print(f"Screen {screen.index}: {screen.w}x{screen.h} at ({screen.x}, {screen.y})")
Window Lifecycle¶
# Creation
win = wa.window(100, 100, 200, 200)
# Visibility
win.hide()
win.show()
# Z-order
win.raise_window()
# Destruction
win.close() # Explicit
# or let it be garbage collected
All windows are automatically closed when using the run() context manager.
Next Steps¶
- Windows Guide - Full window documentation
- Animation Guide - Animation in depth
- API Reference - Complete API documentation