Cross-platform windowing and multimedia library for Python with OpenGL graphics, event handling, and audio/video playback
Cross-platform window creation, management, and event handling.
class pyglet.window.Window:
"""Platform-independent application window with OpenGL context"""
__init__(width=None, height=None, caption=None, resizable=False,
style=WINDOW_STYLE_DEFAULT, fullscreen=False, visible=True,
vsync=True, display=None, screen=None, config=None, context=None,
mode=None, file_drops=False)| Property | Type | Description |
|---|---|---|
caption | str | Window title |
width, height | int | Window dimensions (pixels) |
resizable | bool | Can be resized by user |
fullscreen | bool | Fullscreen mode |
visible | bool | Window visibility |
vsync | bool | Vertical sync |
display | Display | Display device (read-only) |
context | Context | OpenGL context (read-only) |
config | Config | OpenGL config (read-only) |
screen | Screen | Screen for fullscreen (read-only) |
scale | float | DPI scale factor (read-only) |
dpi | int | DPI value (read-only) |
size | tuple | (width, height) (read-only) |
aspect_ratio | float | width/height (read-only) |
projection | Mat4 | Projection matrix (read-only) |
view | Mat4 | View matrix (read-only) |
viewport | tuple | (x, y, width, height) (read-only) |
invalid | bool | Needs redraw flag |
# Window control
def close()
def switch_to() # Make GL context current
def flip() # Swap buffers
def clear() # Clear with background
def draw(dt) # Full draw cycle (switch_to + on_draw + on_refresh + flip)
# Configuration
def set_caption(caption: str)
def set_size(width: int, height: int)
def set_location(x: int, y: int)
def get_size() -> tuple # (width, height)
def get_location() -> tuple # (x, y)
def get_framebuffer_size() -> tuple # HiDPI may differ from window size
def get_pixel_ratio() -> float # framebuffer/window size ratio
def set_minimum_size(width: int, height: int)
def set_maximum_size(width: int, height: int)
def set_visible(visible: bool = True)
def set_fullscreen(fullscreen: bool = True, screen=None, mode=None, width=None, height=None)
def minimize()
def maximize()
def activate() # Bring to foreground
# Display settings
def set_vsync(vsync: bool)
def set_icon(*images) # Set window icon
# Mouse
def set_mouse_visible(visible: bool = True)
def set_mouse_cursor(cursor=None) # None for default
def get_system_mouse_cursor(name: str) -> MouseCursor
def set_mouse_platform_visible(platform_visible=None)
def set_mouse_passthrough(state: bool) # Click-through window
def set_exclusive_mouse(exclusive: bool = True) # Hide and constrain
# Keyboard
def set_exclusive_keyboard(exclusive: bool = True) # Capture shortcuts
# Clipboard
def get_clipboard_text() -> str
def set_clipboard_text(text: str)
# Events
def dispatch_events() # For custom event loops (use pyglet.app.run() instead)
def push_handlers(*args, **kwargs)
def pop_handlers()
def remove_handlers(*args, **kwargs)
def set_handler(name: str, handler: callable)
def set_handlers(*args, **kwargs)
def remove_handler(name: str, handler: callable)Register with @window.event decorator or window.push_handlers():
| Event | Signature | Description |
|---|---|---|
on_activate | () | Window gained focus |
on_close | () | Close requested (return False to prevent) |
on_context_lost | () | OpenGL context lost |
on_context_state_lost | () | OpenGL state lost |
on_deactivate | () | Window lost focus |
on_draw | () | Window needs redraw |
on_expose | () | Window uncovered |
on_hide | () | Window hidden |
on_show | () | Window shown |
on_move | (x: int, y: int) | Window moved |
on_resize | (width: int, height: int) | Window resized |
on_refresh | (dt: float) | Window refreshed (after on_draw) |
on_scale | (scale: float, dpi: int) | DPI changed |
on_key_press | (symbol: int, modifiers: int) | Key pressed |
on_key_release | (symbol: int, modifiers: int) | Key released |
on_text | (text: str) | Unicode text entered |
on_text_motion | (motion: int) | Text cursor motion |
on_text_motion_select | (motion: int) | Text cursor motion with selection |
on_mouse_enter | (x: int, y: int) | Mouse entered window |
on_mouse_leave | (x: int, y: int) | Mouse left window |
on_mouse_motion | (x: int, y: int, dx: int, dy: int) | Mouse moved |
on_mouse_drag | (x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int) | Mouse dragged |
on_mouse_press | (x: int, y: int, button: int, modifiers: int) | Mouse button pressed |
on_mouse_release | (x: int, y: int, button: int, modifiers: int) | Mouse button released |
on_mouse_scroll | (x: int, y: int, scroll_x: float, scroll_y: float) | Mouse wheel scrolled |
on_file_drop | (x: int, y: int, paths: list) | Files dropped (requires file_drops=True) |
# Get display
display = pyglet.display.get_display(name=None) # None for default
screens = display.get_screens() # list of Screen
default_screen = display.get_default_screen()
windows = display.get_windows() # list of Window
# Screen properties
screen.x, screen.y # Position
screen.width, screen.height # Dimensions
screen.xdpi, screen.ydpi # DPI
# Screen methods
modes = screen.get_modes() # Available ScreenMode objects
mode = screen.get_mode() # Current mode
screen.set_mode(mode)
screen.restore_mode()
dpi = screen.get_dpi()
scale = screen.get_scale() # 1.0 standard, 2.0 for 2x scaling
display_id = screen.get_display_id()
name = screen.get_monitor_name()
# ScreenMode properties
mode.width, mode.height # Resolution
mode.depth # Color depth (bits)
mode.rate # Refresh rate (Hz)from pyglet.window import key, mouse
# Keyboard state
keys = key.KeyStateHandler()
window.push_handlers(keys)
if keys[key.LEFT]: # Check if key is pressed
# Move left
# Mouse state
buttons = mouse.MouseStateHandler()
window.push_handlers(buttons)
if buttons[mouse.LEFT]: # Check if button is pressed
# Handle mouse buttonclass pyglet.window.FPSDisplay:
"""Frame rate counter display"""
__init__(window, color=(127,127,127,127), samples=240)
update_period: float = 0.25 # Update frequency
label: pyglet.text.Label # Display label
def update() # Update FPS (called automatically)
def draw() # Draw counter
# Usage
fps_display = pyglet.window.FPSDisplay(window)
@window.event
def on_draw():
window.clear()
# ... draw game
fps_display.draw()pyglet.window.WINDOW_STYLE_DEFAULT # Standard with title bar
pyglet.window.WINDOW_STYLE_DIALOG # Dialog style
pyglet.window.WINDOW_STYLE_TOOL # Tool window
pyglet.window.WINDOW_STYLE_BORDERLESS # No borders
pyglet.window.WINDOW_STYLE_TRANSPARENT # Transparent, interactable
pyglet.window.WINDOW_STYLE_OVERLAY # Transparent, topmost, click-through# System cursors
cursor = window.get_system_mouse_cursor(name)
window.set_mouse_cursor(cursor)
# Cursor constants
CURSOR_DEFAULT, CURSOR_CROSSHAIR, CURSOR_HAND, CURSOR_HELP, CURSOR_NO,
CURSOR_SIZE, CURSOR_SIZE_UP, CURSOR_SIZE_UP_RIGHT, CURSOR_SIZE_RIGHT,
CURSOR_SIZE_DOWN_RIGHT, CURSOR_SIZE_DOWN, CURSOR_SIZE_DOWN_LEFT,
CURSOR_SIZE_LEFT, CURSOR_SIZE_UP_LEFT, CURSOR_SIZE_UP_DOWN,
CURSOR_SIZE_LEFT_RIGHT, CURSOR_TEXT, CURSOR_WAIT, CURSOR_WAIT_ARROW
# Custom cursor
from pyglet.window import ImageMouseCursor
image = pyglet.image.load('cursor.png')
cursor = ImageMouseCursor(image, hot_x=0, hot_y=0)
window.set_mouse_cursor(cursor)from pyglet.window import key
# Letters: key.A through key.Z
# Numbers: key._0 through key._9 (top row)
# Numpad: key.NUM_0 through key.NUM_9
# Function: key.F1 through key.F24
# Special keys
key.ENTER, key.ESCAPE, key.SPACE, key.TAB, key.BACKSPACE, key.DELETE,
key.INSERT, key.HOME, key.END, key.PAGEUP, key.PAGEDOWN
# Arrows
key.LEFT, key.RIGHT, key.UP, key.DOWN
# Modifiers (bitwise flags for checking)
key.MOD_SHIFT, key.MOD_CTRL, key.MOD_ALT, key.MOD_CAPSLOCK,
key.MOD_NUMLOCK, key.MOD_SCROLLLOCK, key.MOD_COMMAND, key.MOD_OPTION,
key.MOD_WINDOWS, key.MOD_FUNCTION
key.MOD_ACCEL # Ctrl on Windows/Linux, Command on macOS
# Text motion constants (for on_text_motion events)
key.MOTION_UP, key.MOTION_DOWN, key.MOTION_LEFT, key.MOTION_RIGHT,
key.MOTION_NEXT_WORD, key.MOTION_PREVIOUS_WORD,
key.MOTION_BEGINNING_OF_LINE, key.MOTION_END_OF_LINE,
key.MOTION_NEXT_PAGE, key.MOTION_PREVIOUS_PAGE,
key.MOTION_BEGINNING_OF_FILE, key.MOTION_END_OF_FILE,
key.MOTION_BACKSPACE, key.MOTION_DELETE,
key.MOTION_COPY, key.MOTION_PASTE
# Utility functions
key.symbol_string(symbol) -> str # Get key name
key.modifiers_string(modifiers) -> str # Get modifier names
key.motion_string(motion) -> str # Get motion name
key.user_key(scancode) -> int # Platform-specific key mappingfrom pyglet.window import mouse
# Buttons
mouse.LEFT, mouse.MIDDLE, mouse.RIGHT, mouse.MOUSE4, mouse.MOUSE5
# Utility
mouse.buttons_string(buttons) -> str # Get button namesfrom pyglet.window.event import WindowEventLogger
window = pyglet.window.Window()
logger = WindowEventLogger() # Logs to stdout by default
window.push_handlers(logger)
# Or log to file
with open('events.log', 'w') as f:
logger = WindowEventLogger(f)
window.push_handlers(logger)window = pyglet.window.Window(800, 600, 'My App')
@window.event
def on_draw():
window.clear()
pyglet.app.run()@window.event
def on_key_press(symbol, modifiers):
if symbol == key.F and modifiers & key.MOD_CTRL:
window.set_fullscreen(not window.fullscreen)
elif symbol == key.ESCAPE:
if window.fullscreen:
window.set_fullscreen(False)
else:
pyglet.app.exit()display = pyglet.display.get_display()
screens = display.get_screens()
print(f"Found {len(screens)} screens")
for i, screen in enumerate(screens):
print(f"Screen {i}: {screen.width}x{screen.height} @ ({screen.x},{screen.y})")
# Create window on specific screen
window = pyglet.window.Window(screen=screens[1])window = pyglet.window.Window(800, 600, resizable=True)
@window.event
def on_resize(width, height):
# Maintain 4:3 aspect ratio
target_aspect = 4/3
current_aspect = width/height
if current_aspect > target_aspect:
# Too wide
new_width = int(height * target_aspect)
window.set_size(new_width, height)
elif current_aspect < target_aspect:
# Too tall
new_height = int(width / target_aspect)
window.set_size(width, new_height)# Hide system cursor and draw custom
window.set_mouse_visible(False)
cursor_sprite = pyglet.sprite.Sprite(cursor_img)
@window.event
def on_mouse_motion(x, y, dx, dy):
cursor_sprite.position = (x, y)
@window.event
def on_draw():
window.clear()
# ... draw game
cursor_sprite.draw()window.set_exclusive_mouse(True)
@window.event
def on_mouse_motion(x, y, dx, dy):
# dx/dy are relative motion
camera.rotate(dx * sensitivity, dy * sensitivity)
@window.event
def on_key_press(symbol, modifiers):
if symbol == key.ESCAPE:
window.set_exclusive_mouse(False)class pyglet.window.WindowException(Exception):
"""Base window exception"""
class pyglet.window.NoSuchDisplayException(WindowException):
"""Display not found"""
class pyglet.window.NoSuchConfigException(WindowException):
"""OpenGL config not found"""
class pyglet.window.NoSuchScreenModeException(WindowException):
"""Screen mode cannot be set"""
class pyglet.window.MouseCursorException(WindowException):
"""Mouse cursor error"""vsync=True to limit frame rate to monitor refresh (default)window.invalid flag controls when window needs redraw (batch operations)on_refresh event for post-draw effects (dt parameter available)get_framebuffer_size() for actual pixel countInstall with Tessl CLI
npx tessl i tessl/pypi-pyglet