Cross-platform windowing and multimedia library for Python with OpenGL graphics, event handling, and audio/video playback
Interactive UI components: buttons, sliders, text entry, and containers.
from pyglet import gui
# Frame (manages widget events)
frame = gui.Frame(window)
# Button
button = gui.PushButton(x=100, y=100, pressed=pressed_img, unpressed=unpressed_img)
frame.add_widget(button)
@button.event
def on_press():
print("Button pressed!")
# Slider
slider = gui.Slider(x=100, y=50, base=base_img, knob=knob_img)
frame.add_widget(slider)
@slider.event
def on_change(value):
print(f"Value: {value}")
# Text entry
text_entry = gui.TextEntry('Initial text', x=100, y=150, width=200)
frame.add_widget(text_entry)class pyglet.gui.Frame:
"""Container managing widget event dispatching"""
__init__(window, enable=True, cell_size=64, order=0)
# Methods
def add_widget(widget)
def remove_widget(widget)
# Properties
enable: bool # Enable/disable event handling
widgets: list # All managed widgetsclass pyglet.gui.PushButton(WidgetBase):
"""Clickable button"""
__init__(x, y, pressed, unpressed, hover=None, batch=None, group=None)
# Properties
value: bool # Current pressed state
enabled: bool
# Events
@button.event
def on_press():
"""Button pressed"""
@button.event
def on_release():
"""Button released"""
class pyglet.gui.ToggleButton(PushButton):
"""Button with on/off state"""
# Same as PushButton but maintains toggle stateclass pyglet.gui.Slider(WidgetBase):
"""Horizontal slider"""
__init__(x, y, base, knob, edge=0, batch=None, group=None)
# Properties
value: float # 0.0 to 1.0
min, max: float # Value range
enabled: bool
# Events
@slider.event
def on_change(value):
"""Value changed"""class pyglet.gui.TextEntry(WidgetBase):
"""Single-line text input"""
__init__(text, x, y, width, color=(255,255,255,255), text_color=(0,0,0,255),
caret_color=(0,0,0), batch=None, group=None)
# Properties
text: str
focus: bool # Has keyboard focus
enabled: bool
# Events
@text_entry.event
def on_commit(text):
"""Enter pressed"""class pyglet.gui.NinePatch:
"""Scalable UI element from 9-slice image"""
__init__(texture_region, left, right, top, bottom)
def get_subregion(x, y, width, height) -> TextureRegionAll widgets inherit from:
class pyglet.gui.WidgetBase:
"""Base widget class"""
# Properties
x, y: int
width, height: int
enabled: bool
batch: Batch
group: Group
# Events
def on_mouse_press(x, y, button, modifiers)
def on_mouse_release(x, y, button, modifiers)
def on_mouse_drag(x, y, dx, dy, buttons, modifiers)
def on_mouse_motion(x, y, dx, dy)from pyglet import gui, image, graphics
window = pyglet.window.Window()
batch = graphics.Batch()
frame = gui.Frame(window)
# Load button images
pressed = image.load('button_pressed.png')
unpressed = image.load('button_unpressed.png')
# Create button grid
buttons = []
for row in range(3):
for col in range(3):
x = 50 + col * 120
y = 400 - row * 80
button = gui.PushButton(x, y, pressed, unpressed, batch=batch)
button.id = row * 3 + col
frame.add_widget(button)
buttons.append(button)
@button.event
def on_press(btn=button):
print(f"Button {btn.id} pressed")
@window.event
def on_draw():
window.clear()
batch.draw()
pyglet.app.run()slider = gui.Slider(x=100, y=100, base=base_img, knob=knob_img, batch=batch)
frame.add_widget(slider)
@slider.event
def on_change(value):
# value is 0.0 to 1.0
music_player.volume = value
volume_label.text = f"Volume: {int(value * 100)}%"text_entry = gui.TextEntry(
'Enter name...',
x=100, y=200, width=300,
batch=batch
)
frame.add_widget(text_entry)
text_entry.focus = True
@text_entry.event
def on_commit(text):
print(f"Submitted: {text}")
text_entry.text = '' # Clear
@window.event
def on_key_press(symbol, modifiers):
if symbol == pyglet.window.key.ESCAPE:
text_entry.focus = Falseclass CustomButton(gui.WidgetBase):
def __init__(self, x, y, width, height, text):
super().__init__(x, y, width, height)
self.text = text
self.pressed = False
# Create visual elements
self.bg = pyglet.shapes.Rectangle(
x, y, width, height,
color=(100, 100, 200)
)
self.label = pyglet.text.Label(
text,
x=x + width//2, y=y + height//2,
anchor_x='center', anchor_y='center'
)
def on_mouse_press(self, x, y, button, modifiers):
if self._check_hit(x, y):
self.pressed = True
self.bg.color = (150, 150, 255)
self.dispatch_event('on_press')
def on_mouse_release(self, x, y, button, modifiers):
if self.pressed:
self.pressed = False
self.bg.color = (100, 100, 200)
def _check_hit(self, x, y):
return (self.x <= x <= self.x + self.width and
self.y <= y <= self.y + self.height)
CustomButton.register_event_type('on_press')class Menu:
def __init__(self, window):
self.window = window
self.frame = gui.Frame(window)
self.batch = pyglet.graphics.Batch()
self.buttons = []
def add_button(self, text, callback, y_offset):
# Create button (simplified)
button = gui.PushButton(
x=window.width // 2 - 100,
y=window.height // 2 + y_offset,
pressed=pressed_img,
unpressed=unpressed_img,
batch=self.batch
)
button.callback = callback
self.frame.add_widget(button)
self.buttons.append(button)
@button.event
def on_press():
callback()
def draw(self):
self.batch.draw()
# Usage
menu = Menu(window)
menu.add_button("Start", lambda: print("Start game"), 50)
menu.add_button("Options", lambda: print("Options"), 0)
menu.add_button("Quit", lambda: pyglet.app.exit(), -50)enabled=False on hidden widgetsInstall with Tessl CLI
npx tessl i tessl/pypi-pyglet@2.1.1