0
# Windowing and Display
1
2
Cross-platform window creation, management, and event handling.
3
4
## Window Class
5
6
```python
7
class pyglet.window.Window:
8
"""Platform-independent application window with OpenGL context"""
9
10
__init__(width=None, height=None, caption=None, resizable=False,
11
style=WINDOW_STYLE_DEFAULT, fullscreen=False, visible=True,
12
vsync=True, display=None, screen=None, config=None, context=None,
13
mode=None, file_drops=False)
14
```
15
16
### Properties
17
18
| Property | Type | Description |
19
|----------|------|-------------|
20
| `caption` | str | Window title |
21
| `width`, `height` | int | Window dimensions (pixels) |
22
| `resizable` | bool | Can be resized by user |
23
| `fullscreen` | bool | Fullscreen mode |
24
| `visible` | bool | Window visibility |
25
| `vsync` | bool | Vertical sync |
26
| `display` | Display | Display device (read-only) |
27
| `context` | Context | OpenGL context (read-only) |
28
| `config` | Config | OpenGL config (read-only) |
29
| `screen` | Screen | Screen for fullscreen (read-only) |
30
| `scale` | float | DPI scale factor (read-only) |
31
| `dpi` | int | DPI value (read-only) |
32
| `size` | tuple | (width, height) (read-only) |
33
| `aspect_ratio` | float | width/height (read-only) |
34
| `projection` | Mat4 | Projection matrix (read-only) |
35
| `view` | Mat4 | View matrix (read-only) |
36
| `viewport` | tuple | (x, y, width, height) (read-only) |
37
| `invalid` | bool | Needs redraw flag |
38
39
### Core Methods
40
41
```python
42
# Window control
43
def close()
44
def switch_to() # Make GL context current
45
def flip() # Swap buffers
46
def clear() # Clear with background
47
def draw(dt) # Full draw cycle (switch_to + on_draw + on_refresh + flip)
48
49
# Configuration
50
def set_caption(caption: str)
51
def set_size(width: int, height: int)
52
def set_location(x: int, y: int)
53
def get_size() -> tuple # (width, height)
54
def get_location() -> tuple # (x, y)
55
def get_framebuffer_size() -> tuple # HiDPI may differ from window size
56
def get_pixel_ratio() -> float # framebuffer/window size ratio
57
def set_minimum_size(width: int, height: int)
58
def set_maximum_size(width: int, height: int)
59
def set_visible(visible: bool = True)
60
def set_fullscreen(fullscreen: bool = True, screen=None, mode=None, width=None, height=None)
61
def minimize()
62
def maximize()
63
def activate() # Bring to foreground
64
65
# Display settings
66
def set_vsync(vsync: bool)
67
def set_icon(*images) # Set window icon
68
69
# Mouse
70
def set_mouse_visible(visible: bool = True)
71
def set_mouse_cursor(cursor=None) # None for default
72
def get_system_mouse_cursor(name: str) -> MouseCursor
73
def set_mouse_platform_visible(platform_visible=None)
74
def set_mouse_passthrough(state: bool) # Click-through window
75
def set_exclusive_mouse(exclusive: bool = True) # Hide and constrain
76
77
# Keyboard
78
def set_exclusive_keyboard(exclusive: bool = True) # Capture shortcuts
79
80
# Clipboard
81
def get_clipboard_text() -> str
82
def set_clipboard_text(text: str)
83
84
# Events
85
def dispatch_events() # For custom event loops (use pyglet.app.run() instead)
86
def push_handlers(*args, **kwargs)
87
def pop_handlers()
88
def remove_handlers(*args, **kwargs)
89
def set_handler(name: str, handler: callable)
90
def set_handlers(*args, **kwargs)
91
def remove_handler(name: str, handler: callable)
92
```
93
94
## Window Events
95
96
Register with `@window.event` decorator or `window.push_handlers()`:
97
98
| Event | Signature | Description |
99
|-------|-----------|-------------|
100
| `on_activate` | `()` | Window gained focus |
101
| `on_close` | `()` | Close requested (return False to prevent) |
102
| `on_context_lost` | `()` | OpenGL context lost |
103
| `on_context_state_lost` | `()` | OpenGL state lost |
104
| `on_deactivate` | `()` | Window lost focus |
105
| `on_draw` | `()` | Window needs redraw |
106
| `on_expose` | `()` | Window uncovered |
107
| `on_hide` | `()` | Window hidden |
108
| `on_show` | `()` | Window shown |
109
| `on_move` | `(x: int, y: int)` | Window moved |
110
| `on_resize` | `(width: int, height: int)` | Window resized |
111
| `on_refresh` | `(dt: float)` | Window refreshed (after on_draw) |
112
| `on_scale` | `(scale: float, dpi: int)` | DPI changed |
113
| `on_key_press` | `(symbol: int, modifiers: int)` | Key pressed |
114
| `on_key_release` | `(symbol: int, modifiers: int)` | Key released |
115
| `on_text` | `(text: str)` | Unicode text entered |
116
| `on_text_motion` | `(motion: int)` | Text cursor motion |
117
| `on_text_motion_select` | `(motion: int)` | Text cursor motion with selection |
118
| `on_mouse_enter` | `(x: int, y: int)` | Mouse entered window |
119
| `on_mouse_leave` | `(x: int, y: int)` | Mouse left window |
120
| `on_mouse_motion` | `(x: int, y: int, dx: int, dy: int)` | Mouse moved |
121
| `on_mouse_drag` | `(x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int)` | Mouse dragged |
122
| `on_mouse_press` | `(x: int, y: int, button: int, modifiers: int)` | Mouse button pressed |
123
| `on_mouse_release` | `(x: int, y: int, button: int, modifiers: int)` | Mouse button released |
124
| `on_mouse_scroll` | `(x: int, y: int, scroll_x: float, scroll_y: float)` | Mouse wheel scrolled |
125
| `on_file_drop` | `(x: int, y: int, paths: list)` | Files dropped (requires file_drops=True) |
126
127
## Display & Screen
128
129
```python
130
# Get display
131
display = pyglet.display.get_display(name=None) # None for default
132
screens = display.get_screens() # list of Screen
133
default_screen = display.get_default_screen()
134
windows = display.get_windows() # list of Window
135
136
# Screen properties
137
screen.x, screen.y # Position
138
screen.width, screen.height # Dimensions
139
screen.xdpi, screen.ydpi # DPI
140
141
# Screen methods
142
modes = screen.get_modes() # Available ScreenMode objects
143
mode = screen.get_mode() # Current mode
144
screen.set_mode(mode)
145
screen.restore_mode()
146
dpi = screen.get_dpi()
147
scale = screen.get_scale() # 1.0 standard, 2.0 for 2x scaling
148
display_id = screen.get_display_id()
149
name = screen.get_monitor_name()
150
151
# ScreenMode properties
152
mode.width, mode.height # Resolution
153
mode.depth # Color depth (bits)
154
mode.rate # Refresh rate (Hz)
155
```
156
157
## Input State Tracking
158
159
```python
160
from pyglet.window import key, mouse
161
162
# Keyboard state
163
keys = key.KeyStateHandler()
164
window.push_handlers(keys)
165
if keys[key.LEFT]: # Check if key is pressed
166
# Move left
167
168
# Mouse state
169
buttons = mouse.MouseStateHandler()
170
window.push_handlers(buttons)
171
if buttons[mouse.LEFT]: # Check if button is pressed
172
# Handle mouse button
173
```
174
175
## FPS Display
176
177
```python
178
class pyglet.window.FPSDisplay:
179
"""Frame rate counter display"""
180
181
__init__(window, color=(127,127,127,127), samples=240)
182
183
update_period: float = 0.25 # Update frequency
184
label: pyglet.text.Label # Display label
185
186
def update() # Update FPS (called automatically)
187
def draw() # Draw counter
188
189
# Usage
190
fps_display = pyglet.window.FPSDisplay(window)
191
192
@window.event
193
def on_draw():
194
window.clear()
195
# ... draw game
196
fps_display.draw()
197
```
198
199
## Window Styles
200
201
```python
202
pyglet.window.WINDOW_STYLE_DEFAULT # Standard with title bar
203
pyglet.window.WINDOW_STYLE_DIALOG # Dialog style
204
pyglet.window.WINDOW_STYLE_TOOL # Tool window
205
pyglet.window.WINDOW_STYLE_BORDERLESS # No borders
206
pyglet.window.WINDOW_STYLE_TRANSPARENT # Transparent, interactable
207
pyglet.window.WINDOW_STYLE_OVERLAY # Transparent, topmost, click-through
208
```
209
210
## Mouse Cursors
211
212
```python
213
# System cursors
214
cursor = window.get_system_mouse_cursor(name)
215
window.set_mouse_cursor(cursor)
216
217
# Cursor constants
218
CURSOR_DEFAULT, CURSOR_CROSSHAIR, CURSOR_HAND, CURSOR_HELP, CURSOR_NO,
219
CURSOR_SIZE, CURSOR_SIZE_UP, CURSOR_SIZE_UP_RIGHT, CURSOR_SIZE_RIGHT,
220
CURSOR_SIZE_DOWN_RIGHT, CURSOR_SIZE_DOWN, CURSOR_SIZE_DOWN_LEFT,
221
CURSOR_SIZE_LEFT, CURSOR_SIZE_UP_LEFT, CURSOR_SIZE_UP_DOWN,
222
CURSOR_SIZE_LEFT_RIGHT, CURSOR_TEXT, CURSOR_WAIT, CURSOR_WAIT_ARROW
223
224
# Custom cursor
225
from pyglet.window import ImageMouseCursor
226
image = pyglet.image.load('cursor.png')
227
cursor = ImageMouseCursor(image, hot_x=0, hot_y=0)
228
window.set_mouse_cursor(cursor)
229
```
230
231
## Keyboard Constants
232
233
```python
234
from pyglet.window import key
235
236
# Letters: key.A through key.Z
237
# Numbers: key._0 through key._9 (top row)
238
# Numpad: key.NUM_0 through key.NUM_9
239
# Function: key.F1 through key.F24
240
241
# Special keys
242
key.ENTER, key.ESCAPE, key.SPACE, key.TAB, key.BACKSPACE, key.DELETE,
243
key.INSERT, key.HOME, key.END, key.PAGEUP, key.PAGEDOWN
244
245
# Arrows
246
key.LEFT, key.RIGHT, key.UP, key.DOWN
247
248
# Modifiers (bitwise flags for checking)
249
key.MOD_SHIFT, key.MOD_CTRL, key.MOD_ALT, key.MOD_CAPSLOCK,
250
key.MOD_NUMLOCK, key.MOD_SCROLLLOCK, key.MOD_COMMAND, key.MOD_OPTION,
251
key.MOD_WINDOWS, key.MOD_FUNCTION
252
key.MOD_ACCEL # Ctrl on Windows/Linux, Command on macOS
253
254
# Text motion constants (for on_text_motion events)
255
key.MOTION_UP, key.MOTION_DOWN, key.MOTION_LEFT, key.MOTION_RIGHT,
256
key.MOTION_NEXT_WORD, key.MOTION_PREVIOUS_WORD,
257
key.MOTION_BEGINNING_OF_LINE, key.MOTION_END_OF_LINE,
258
key.MOTION_NEXT_PAGE, key.MOTION_PREVIOUS_PAGE,
259
key.MOTION_BEGINNING_OF_FILE, key.MOTION_END_OF_FILE,
260
key.MOTION_BACKSPACE, key.MOTION_DELETE,
261
key.MOTION_COPY, key.MOTION_PASTE
262
263
# Utility functions
264
key.symbol_string(symbol) -> str # Get key name
265
key.modifiers_string(modifiers) -> str # Get modifier names
266
key.motion_string(motion) -> str # Get motion name
267
key.user_key(scancode) -> int # Platform-specific key mapping
268
```
269
270
## Mouse Constants
271
272
```python
273
from pyglet.window import mouse
274
275
# Buttons
276
mouse.LEFT, mouse.MIDDLE, mouse.RIGHT, mouse.MOUSE4, mouse.MOUSE5
277
278
# Utility
279
mouse.buttons_string(buttons) -> str # Get button names
280
```
281
282
## Event Logger (Debugging)
283
284
```python
285
from pyglet.window.event import WindowEventLogger
286
287
window = pyglet.window.Window()
288
logger = WindowEventLogger() # Logs to stdout by default
289
window.push_handlers(logger)
290
291
# Or log to file
292
with open('events.log', 'w') as f:
293
logger = WindowEventLogger(f)
294
window.push_handlers(logger)
295
```
296
297
## Common Patterns
298
299
### Basic Window
300
```python
301
window = pyglet.window.Window(800, 600, 'My App')
302
303
@window.event
304
def on_draw():
305
window.clear()
306
307
pyglet.app.run()
308
```
309
310
### Fullscreen Toggle
311
```python
312
@window.event
313
def on_key_press(symbol, modifiers):
314
if symbol == key.F and modifiers & key.MOD_CTRL:
315
window.set_fullscreen(not window.fullscreen)
316
elif symbol == key.ESCAPE:
317
if window.fullscreen:
318
window.set_fullscreen(False)
319
else:
320
pyglet.app.exit()
321
```
322
323
### Multi-Monitor
324
```python
325
display = pyglet.display.get_display()
326
screens = display.get_screens()
327
print(f"Found {len(screens)} screens")
328
for i, screen in enumerate(screens):
329
print(f"Screen {i}: {screen.width}x{screen.height} @ ({screen.x},{screen.y})")
330
331
# Create window on specific screen
332
window = pyglet.window.Window(screen=screens[1])
333
```
334
335
### Resizable Window with Aspect Ratio
336
```python
337
window = pyglet.window.Window(800, 600, resizable=True)
338
339
@window.event
340
def on_resize(width, height):
341
# Maintain 4:3 aspect ratio
342
target_aspect = 4/3
343
current_aspect = width/height
344
if current_aspect > target_aspect:
345
# Too wide
346
new_width = int(height * target_aspect)
347
window.set_size(new_width, height)
348
elif current_aspect < target_aspect:
349
# Too tall
350
new_height = int(width / target_aspect)
351
window.set_size(width, new_height)
352
```
353
354
### Custom Cursor
355
```python
356
# Hide system cursor and draw custom
357
window.set_mouse_visible(False)
358
cursor_sprite = pyglet.sprite.Sprite(cursor_img)
359
360
@window.event
361
def on_mouse_motion(x, y, dx, dy):
362
cursor_sprite.position = (x, y)
363
364
@window.event
365
def on_draw():
366
window.clear()
367
# ... draw game
368
cursor_sprite.draw()
369
```
370
371
### Exclusive Mouse (FPS-style)
372
```python
373
window.set_exclusive_mouse(True)
374
375
@window.event
376
def on_mouse_motion(x, y, dx, dy):
377
# dx/dy are relative motion
378
camera.rotate(dx * sensitivity, dy * sensitivity)
379
380
@window.event
381
def on_key_press(symbol, modifiers):
382
if symbol == key.ESCAPE:
383
window.set_exclusive_mouse(False)
384
```
385
386
## Exceptions
387
388
```python
389
class pyglet.window.WindowException(Exception):
390
"""Base window exception"""
391
392
class pyglet.window.NoSuchDisplayException(WindowException):
393
"""Display not found"""
394
395
class pyglet.window.NoSuchConfigException(WindowException):
396
"""OpenGL config not found"""
397
398
class pyglet.window.NoSuchScreenModeException(WindowException):
399
"""Screen mode cannot be set"""
400
401
class pyglet.window.MouseCursorException(WindowException):
402
"""Mouse cursor error"""
403
```
404
405
## Performance Notes
406
407
- Use `vsync=True` to limit frame rate to monitor refresh (default)
408
- `window.invalid` flag controls when window needs redraw (batch operations)
409
- Minimize window resizing operations (expensive)
410
- Use `on_refresh` event for post-draw effects (dt parameter available)
411
- HiDPI: Use `get_framebuffer_size()` for actual pixel count
412