Python Arcade Library Logo

About

  • Introduction
    • Learning Resources
      • Getting Started
      • Experienced Developers
    • Community driven
    • History
  • Frequently asked questions
    • Can I use Arcade resources in my own educational materials?
    • Can I use Arcade in a commercial project?
    • Can I copy and adapt example code for my own projects?
    • Can Arcade run on…?
      • Windows, Mac, and Linux
      • Raspberry Pi and Other SBCs
      • Web
      • Mobile
  • Freedom to Remix and Share
    • Yes, You Can Make Commercial Games!
      • How Do I Publish My Games?
    • The MIT License
    • Public Domain Assets
      • Where are all these assets from?
    • What About Academia?
  • For Educators & Researchers
    • Citation Template
    • Version Considerations
      • Arcade Textbook
    • 2.6.X Maintenance?
    • Raspberry Pi and other SBCs
      • SBC Purchasing Rules of Thumb

Getting Started

  • Install
    • Requirements
      • Windows, Linux, and Intel Mac
      • Raspberry Pi and Other ARM SBCs
    • Using pip
    • Development version
    • Running examples
    • Batteries Included
  • Examples
    • Starting Templates
    • Primitives
      • Drawing Primitives
      • Animating Drawing Primitives
      • Faster Drawing with ShapeElementLists
    • Sprites
      • Player Movement
      • Non-Player Movement
      • Easing
      • Calculating a Path
      • Sprite Properties
      • Games with Levels
      • Shooting with Sprites
    • Audio
      • Sound Effects
      • Music
    • Display Management
      • Resizable Windows
      • Backgrounds
      • Cameras
    • View Management
      • Instruction and Game Over Screens
      • Sectioning a View
    • Platformers
      • Basic Platformers
      • Tiled Map Editor
      • Procedural Generation
    • Graphical User Interface
      • Experimental Widgets
    • Grid-Based Games
    • Advanced
      • Using PyMunk for Physics
      • Frame Buffers
      • OpenGL
    • Concept Games
    • Odds and Ends
      • Particle System
    • Tutorials
    • Stress Tests
  • Tutorials
    • Simple Platformer
      • Step 1 - Install and Open a Window
      • Step 2 - Textures and Sprites
      • Step 3 - Many Sprites with SpriteList
      • Step 4 - Add User Control
      • Step 5 - Add Gravity
      • Step 6 - Resetting
      • Step 7 - Adding a Camera
      • Step 8 - Collecting Coins
      • Step 9 - Adding Sound
      • Step 10 - Adding a Score
      • Step 11 - Using a Scene
      • Step 12 - Loading a Map From a Map Editor
      • Step 13 - More Types of Layers
      • Step 14 - Multiple Levels
    • Pymunk Platformer
      • Common Issues
      • Open a Window
      • Create Constants
      • Create Instance Variables
      • Load and Display Map
      • Add Physics Engine
      • Add Player Movement
      • Add Player Jumping
      • Add Player Animation
      • Shoot Bullets
      • Destroy Bullets and Items
      • Add Moving Platforms
      • Add Ladders
    • Using Views for Start/End Screens
      • Change Main Program to Use a View
      • Add Instruction Screen
      • Game Over Screen
    • Solitaire
      • Open a Window
      • Create Card Sprites
      • Implement Drag and Drop
      • Draw Pile Mats
      • Snap Cards to Piles
      • Shuffle the Cards
      • Track Card Piles
      • Pick Up Card Stacks
      • Deal Out Cards
      • Face Down Cards
      • Restart Game
      • Flip Three From Draw Pile
      • Conclusion
    • Lights
    • Bundling a Game with PyInstaller
      • Bundling a Simple Arcade Script
      • Handling Data Files
      • Troubleshooting
      • Extra Details
      • PyInstaller Documentation
    • Compiling a Game with Nuitka
      • Compiling a Simple Arcade Script
      • But What About Data Files And Folders?
      • Removing The Console Window
      • What About A Custom Taskbar Icon?
      • Additional Information
    • Shaders - Shadertoy
      • Ray-casting Shadows
      • CRT Filter
      • Shader Toy - Glow
      • Shader Toy - Particles
      • Compute Shader
      • GPU Particle Burst
      • Working With Shaders
    • Making a Menu with Arcade’s GUI
      • Step 1: Open a Window
      • Step 2: Switching to Menu View
      • Step 3: Setting Up the Menu View
      • Step 4: Configuring the Menu Buttons
      • Step 5: Finalising the Fake Window aka the Sub Menu
      • Adding a Title label
    • Working With FrameBuffer Objects
  • The Arcade Book
    • Installation
    • Getting Help
    • Tutorials
    • Arcade Skill Tree
  • Built-In Resources
    • Do I have to credit anyone?
    • How do I use these?
    • Top-Level Resources
    • Fonts
      • Kenney TTFs
      • Liberation TTFs
    • GUI Basic Assets
      • Button
      • Checkbox
      • Icons
      • Scroll
      • Simple Checkbox
      • Slider
      • Toggle
      • Window & Panel
    • Image Theme Sets
      • Alien
      • Animated Characters
      • Backgrounds
      • Cards
      • Cybercity Background
      • Enemies
      • Items
      • Miami Synth Parallax
      • Pinball
      • Space Shooter
      • Spritesheets
      • Test Textures
      • Tiles
      • Topdown Tanks
    • Input Prompt
      • Xbox
    • Music
    • Onscreen Controls
      • Flat Dark
      • Flat Light
      • Shaded Dark
      • Shaded Light
    • Sounds
    • Tiled Maps
    • Video

Manual

  • Drawing & Using Sprites
    • Drawing with Sprites and SpriteLists
      • What’s a Sprite?
      • Why SpriteLists?
      • Using Sprites and SpriteLists
      • Using Images with Sprites
      • Viewports, Cameras, and Screens
    • Advanced SpriteList Techniques
      • Draw Order & Sorting
      • Custom Texture Atlases
      • Lazy SpriteLists
  • Keyboard
    • Events
      • What is a keyboard event?
      • How do I handle keyboard events?
    • Modifiers
      • What is a modifier?
      • What does active mean?
      • How do I use modifiers?
      • How do I tell left & right modifers apart?
  • Sound
    • Why Is Sound Important?
    • Sound Basics
      • Loading Sounds
      • Playing Sounds
      • Stopping Sounds
    • Intermediate Loading and Playback
      • Streaming or Static Loading?
      • Intermediate-Level Playback Control
    • Cross-Platform Compatibility
      • The Most Reliable Formats & Features
      • Loading In-Depth
      • Backends Determine Playback Features
      • Choosing the Audio Backend
    • Other Sound Libraries
      • Using Pyglet
      • External Libraries
  • Textures
    • Introduction
    • Texture Uniqueness
    • Texture Cache
    • Custom Textures
  • Event Loop
    • Introduction
      • on_draw()
      • on_update()
      • on_fixed_update()
    • Time
      • Clock
      • FixedClock
      • Up Coming
    • More on Fixed update
      • Death Spiral
      • Update Interpolation
    • Vertical Synchronization
      • What is vertical sync?
      • Vertical sync disabled as a default
  • Camera
    • Key Concepts
      • World Space
      • Screen Space
      • View Matrices
      • Projection Matrices
      • Viewports
    • Key Objects
  • Sections
    • A simple example
    • How to work with Sections
    • Sections configuration and logic with an example
    • Section Unique Events
    • The Section Manager
  • GUI
    • GUI Concepts
      • Classes
      • Drawing
      • UIMixin
      • UIConstructs
      • Available Elements
      • User-interface events
      • Different event systems
    • GUI Layouts
      • Included Layouts
      • When to use which layout?
    • GUI Style
      • Which Widgets Can I Style?
      • Basic Usage
      • Advanced
    • Own Widgets
      • Where to start
      • Example ProgressBar
    • Own Layout
      • Where to start
      • Example CircleLayout
    • GUI Controller Support
      • Basic Setup
      • Advanced Usage
  • Texture Atlas
    • Introduction
    • Size Restriction
    • Resize
    • Default Texture Atlas
    • Custom Atlas
    • Border
    • Updating Texture
    • Removing Texture
    • Rendering Into Atlas
    • Debugging
  • Resource Handles
    • Using Resource Handles
      • How Do I Use Resource Handles?
      • When & Where Can I Use Resource Handles?
      • Adding Your Own Resource Handles
      • Adding your New Resource Handle
    • Adding Multiple Directories to a Resource Handle
    • Cleaner Code with Pathlib
      • Finding your Project Folder
    • More on How Resource Handles Work
      • Implementation Details
    • Resources Handles and PyInstaller/Nuitka one-file builds
  • OpenGL
    • Initialization
    • Garbage Collection & Threads
    • Threads & vsync
    • SpriteList & Threads
    • Writing Raw Bytes to GL Buffers & Textures
  • OpenGL ES Devices: Raspberry Pi, Etc
    • OpenGL ES
    • Supported Raspberry Pi Configurations
      • Operating Systems
    • Unsupported Raspberry Pi Devices
      • Incompatible Older Devices
      • Incompatible New Devices
    • SBC Requirements
      • Standard Python
      • Supported OpenGL ES Versions
      • Arcade’s Binary Dependencies
      • An Adequate Power Supply
  • Performance
    • Collision Detection Performance
      • Why are collisions slow?
      • The Faster Alternatives
      • Spatial Hashing
      • Pymunk Physics Engine
      • Compute Shader
    • Drawing Performance
      • Drawing Shapes
    • Sprite drawing performance
      • An Option for Advanced Users
    • Text drawing performance
    • Loading Performance
      • Loading Screens and Rooms
    • Sound Performance in Depth
      • Static Sounds are for Speed
      • Streaming Saves Memory
  • Headless Arcade
    • Enabling headless mode
    • How is this affecting my code?
    • Examples
      • Simple headless mode
      • Headless mode while extending the Arcade Window
    • Advanced
    • Issues?

Contributing

  • Contributing To Arcade
    • Contributing Code
    • I Can’t Code Yet
      • Tell Us About Documentation Issues
      • Play Games made with Arcade
      • Create Art, Music, and Sound
    • Report Bugs
      • Excellent Bug Reports

Community

  • Community Locations
    • Community Standards
    • Where to Post
    • Other Locations
  • How to Get Help
    • Sharing & Formatting Your Code
      • Formatting for Discord & Github Issues
      • Code Hosting
    • Arcade Version & Basic Environment Info
  • Games made with Arcade
    • User-submitted Games
      • Brazier
      • PhotoShip
      • Space Station Builder
      • Notepad Doodles
      • BoxHead Survivor
      • Temporum
      • SOL Defender
      • Binary Defense
      • Space Invaders
      • Ready or Not?
      • Age of Divisiveness
      • Fishy-Game
      • Adventure
      • Transcience Animation
      • Stellar Arena Demo
      • Battle Bros
      • Rabbit Herder
      • The Great Skeleton War
      • Python Knife Hit
      • Kayzee
      • lixingqiu Games
      • Space Typer
      • FlapPy Bird
      • PyOverheadGame
      • Dungeon
      • Two Worlds
      • Mama Nyah’s House of Tarot
      • Simpson College Spring 2017 CMSC 150 Course
    • Python Discord GameJam 2020
      • 3 Keys on the Run
      • Triple Blocks
      • Triple Vision
      • Hatchlings
      • Gem Matcher
      • Tri-Chess
      • Insane Irradiated Insectz
      • Flimsy Billy’s Coin Dash 3
      • ZeYoughEzh
      • Coin Collector

API Reference

  • Quick Index
  • API Reference
    • Types
      • HasAddSubMul
      • TiledObject
      • SupportsDunderLT
      • SupportsDunderGT
      • AnchorPoint
      • Color
      • RectKwargs
      • Rect
      • LRBT()
      • LBWH()
      • XYWH()
      • XYRR()
      • Viewport()
      • BoxKwargs
      • Box
      • XYZWHD()
      • LBNWHD()
      • LRBTNF()
    • Resources
      • resolve_resource_path()
      • resolve()
      • add_resource_handle()
      • get_resource_handle_paths()
      • list_built_in_assets()
      • load_kenney_fonts()
      • load_liberation_fonts()
    • Primitives
      • draw_arc_filled()
      • draw_arc_outline()
      • draw_circle_filled()
      • draw_circle_outline()
      • draw_ellipse_filled()
      • draw_ellipse_outline()
      • get_points_for_thick_line()
      • draw_line_strip()
      • draw_line()
      • draw_lines()
      • draw_parabola_filled()
      • draw_parabola_outline()
      • draw_point()
      • draw_points()
      • draw_polygon_filled()
      • draw_polygon_outline()
      • draw_texture_rect()
      • draw_sprite()
      • draw_sprite_rect()
      • draw_lrbt_rectangle_outline()
      • draw_lbwh_rectangle_outline()
      • draw_lrbt_rectangle_filled()
      • draw_lbwh_rectangle_filled()
      • draw_rect_outline()
      • draw_rect_filled()
      • draw_triangle_filled()
      • draw_triangle_outline()
    • Shape Lists
      • Shape
      • ShapeElementList
      • create_line()
      • create_line_generic_with_colors()
      • create_line_generic()
      • create_line_strip()
      • create_line_loop()
      • create_lines()
      • create_lines_with_colors()
      • create_polygon()
      • create_rectangle_filled()
      • create_rectangle_outline()
      • get_rectangle_points()
      • create_rectangle()
      • create_rectangle_filled_with_colors()
      • create_rectangles_filled_with_colors()
      • create_triangles_filled_with_colors()
      • create_triangles_strip_filled_with_colors()
      • create_ellipse_filled()
      • create_ellipse_outline()
      • create_ellipse()
      • create_ellipse_filled_with_colors()
    • Sprites
      • load_animated_gif()
      • BasicSprite
      • Sprite
      • SpriteSolidColor
      • SpriteCircle
      • PyMunk
      • PymunkMixin
      • TextureKeyframe
      • TextureAnimation
      • TextureAnimationSprite
      • AnimatedWalkingSprite
    • Camera 2D
      • Camera2D
    • Sprite Lists
      • SpriteSequence
      • SpriteList
      • SpriteListData
      • SpriteListBufferData
      • SpriteListTextureData
      • ReadOnlySpatialHash
      • SpatialHash
      • get_distance_between_sprites()
      • get_closest_sprite()
      • check_for_collision()
      • check_for_collision_with_list()
      • check_for_collision_with_lists()
      • get_sprites_at_point()
      • get_sprites_at_exact_point()
      • get_sprites_in_rect()
    • Sprite Scenes
      • SceneKeyError
      • Scene
    • Clock
      • Clock
      • FixedClock
    • Text
      • Text
      • load_font()
      • create_text_sprite()
      • draw_text()
    • Tiled Map Reader
      • TileMap
      • load_tilemap()
    • Texture Management
      • ImageData
      • Texture
      • load_texture()
      • load_image()
      • load_spritesheet()
      • make_circle_texture()
      • make_soft_circle_texture()
      • make_soft_square_texture()
      • TextureCacheManager
      • SpriteSheet
      • get_default_texture()
      • get_default_image()
    • Hitbox
      • calculate_hit_box_points_simple()
      • calculate_hit_box_points_detailed()
      • HitBoxAlgorithm
      • HitBox
      • RotatableHitBox
      • BoundingHitBoxAlgorithm
      • SimpleHitBoxAlgorithm
      • PymunkHitBoxAlgorithm
    • Texture Transforms
      • VertexOrder
      • Transform
      • Rotate90Transform
      • Rotate180Transform
      • Rotate270Transform
      • FlipLeftRightTransform
      • FlipTopBottomTransform
      • TransposeTransform
      • TransverseTransform
    • Texture Atlas
      • TextureAtlasBase
      • DefaultTextureAtlas
      • AtlasRegion
      • UVData
      • ImageDataRefCounter
      • UniqueTextureRefCounter
    • Performance Information
      • print_timings()
      • clear_timings()
      • get_timings()
      • enable_timings()
      • disable_timings()
      • get_fps()
      • timings_enabled()
      • PerfGraph
    • Physics Engines
      • PhysicsEngineSimple
      • PhysicsEnginePlatformer
      • PymunkPhysicsObject
      • PymunkException
      • PymunkPhysicsEngine
    • Misc Utility Functions
      • configure_logging()
      • Chain
      • as_type()
      • type_name()
      • is_iterable()
      • is_nonstr_iterable()
      • is_str_or_noniterable()
      • grow_sequence()
      • copy_dunders_unimplemented()
      • is_pyodide()
      • is_raspberry_pi()
      • get_raspberry_pi_info()
      • unpack_asfloat_or_point()
    • Geometry Support
      • are_polygons_intersecting()
      • is_point_in_box()
      • get_triangle_orientation()
      • are_lines_intersecting()
      • is_point_in_polygon()
    • Game Controller
      • ControllerManager
      • get_controllers()
    • Joystick
      • get_joysticks()
      • get_game_controllers()
    • Window and View
      • NoOpenGLException
      • Window
      • View
      • get_screens()
      • open_window()
      • get_display_size()
      • get_window()
      • set_window()
      • close_window()
      • run()
      • exit()
      • start_render()
      • finish_render()
      • set_background_color()
      • schedule()
      • unschedule()
      • schedule_once()
      • Section
      • SectionManager
      • get_pixel()
      • get_image()
    • Sound
      • Sound
      • load_sound()
      • play_sound()
      • stop_sound()
    • Advanced Camera Features
      • ZeroProjectionDimension
      • CameraData
      • OrthographicProjectionData
      • PerspectiveProjectionData
      • Projection
      • Projector
      • duplicate_camera_data()
      • constrain_camera_data()
      • orthographic_from_rect()
      • generate_view_matrix()
      • generate_orthographic_matrix()
      • generate_perspective_matrix()
      • project_orthographic()
      • unproject_orthographic()
      • project_perspective()
      • unproject_perspective()
      • OrthographicProjector
      • PerspectiveProjector
      • ViewportProjector
      • DefaultProjector
      • static_from_orthographic()
      • static_from_perspective()
      • static_from_raw_orthographic()
      • static_from_raw_perspective()
      • static_from_matrices()
    • Pathfinding
      • AStarBarrierList
      • astar_calculate_path()
      • has_line_of_sight()
    • Isometric Map (incomplete)
      • isometric_grid_to_screen()
      • screen_to_isometric_grid()
      • create_isometric_grid_lines()
    • Earclip
      • earclip()
    • Easing
      • EasingData
      • linear()
      • smoothstep()
      • ease_in()
      • ease_out()
      • ease_in_out()
      • ease_out_elastic()
      • ease_out_bounce()
      • ease_in_back()
      • ease_out_back()
      • ease_in_sin()
      • ease_out_sin()
      • ease_in_out_sin()
      • easing()
      • ease_angle()
      • ease_angle_update()
      • ease_value()
      • ease_position()
      • ease_update()
    • OpenGL Context
      • ArcadeContext
    • Math
      • clamp()
      • lerp()
      • lerp_2d()
      • lerp_3d()
      • smerp()
      • smerp_2d()
      • smerp_3d()
      • lerp_angle()
      • rand_in_rect()
      • rand_in_circle()
      • rand_on_circle()
      • rand_on_line()
      • rand_angle_360_deg()
      • rand_angle_spread_deg()
      • rand_vec_spread_deg()
      • rand_vec_magnitude()
      • get_distance()
      • rotate_point()
      • rescale_relative_to_point()
      • rotate_around_point()
      • get_angle_degrees()
      • get_angle_radians()
      • quaternion_rotation()
    • Arcade’s Graphics Layer
      • Using This Module
      • Graphics API Gotchas
      • Supported Backends
    • Exceptions
      • OutsideRangeError
      • IntOutsideRangeError
      • FloatOutsideRangeError
      • ByteRangeError
      • NormalizedRangeError
      • PerformanceWarning
      • ReplacementWarning
      • warning()
    • Start/Finish Render
      • StartFinishRenderData
    • Cache
      • crate_str_from_values()
      • crate_str_from_list()
      • HitBoxCache
      • TextureBucket
      • TextureCache
      • ImageDataCache
    • Future Features
      • RenderTargetTexture
      • InputType
      • InputEnum
      • StrEnum
      • ControllerAxes
      • ControllerButtons
      • XBoxControllerButtons
      • PSControllerButtons
      • Keys
      • MouseAxes
      • MouseButtons
      • parse_mapping_input_enum()
      • RawInputManager
      • ActionState
      • InputDevice
      • InputManager
      • Action
      • Axis
      • InputMapping
      • ActionMapping
      • AxisMapping
      • serialize_action()
      • parse_raw_axis()
      • serialize_axis()
      • RawBindBase
      • RawActionMapping
      • RawAxisMapping
      • RawAction
      • RawAxis
      • BackgroundTexture
      • Background
      • BackgroundGroup
      • ParallaxGroup
      • Light
      • LightLayer
      • VideoPlayer
      • VideoPlayerView
    • GUI
      • UIMessageBox
      • UIButtonRow
      • UIDraggableMixin
      • UIMouseFilterMixin
      • UIWindowLikeMixin
      • Surface
      • UIManager
      • NinePatchTexture
      • UIView
    • GUI Widgets
      • FocusMode
      • UIWidget
      • UIInteractiveWidget
      • UIDummy
      • UISpriteWidget
      • UILayout
      • UISpace
      • UITextureButtonStyle
      • UITextureButton
      • UIFlatButtonStyle
      • UIFlatButton
      • UIDropdown
      • UIAnchorLayout
      • UIBoxLayout
      • UIGridLayout
      • UIBaseSlider
      • UISliderStyle
      • UISlider
      • UITextureSlider
      • UILabel
      • UITextWidget
      • UIInputTextStyle
      • UIInputText
      • UITextArea
      • UITextureToggle
      • UIImage
    • GUI Events
      • UIEvent
      • UIMouseEvent
      • UIMouseMovementEvent
      • UIMousePressEvent
      • UIMouseDragEvent
      • UIMouseReleaseEvent
      • UIMouseScrollEvent
      • UIKeyEvent
      • UIKeyPressEvent
      • UIKeyReleaseEvent
      • UITextEvent
      • UITextInputEvent
      • UITextMotionEvent
      • UITextMotionSelectEvent
      • UIOnClickEvent
      • UIOnUpdateEvent
      • UIOnChangeEvent
      • UIOnActionEvent
      • UIControllerEvent
      • UIControllerConnectEvent
      • UIControllerDisconnectEvent
      • UIControllerStickEvent
      • UIControllerTriggerEvent
      • UIControllerButtonEvent
      • UIControllerButtonPressEvent
      • UIControllerButtonReleaseEvent
      • UIControllerDpadEvent
    • GUI Properties
      • Property
      • DictProperty
      • ListProperty
      • bind()
      • unbind()
    • GUI Style
      • UIStyleBase
      • UIStyledWidget
    • GUI Experimental Features
      • UIPasswordInput
      • UIScrollBar
      • UIScrollArea
      • UITypedTextInput
    • arcade.key package
    • arcade.csscolor package
    • arcade.color package
    • arcade.uicolor package
Python Arcade Library
  • GUI Widget Gallery
  • View page source

GUI Widget Gallery

Screen shot of GUI Widget Gallery
2_widgets.py
  1"""An overview of all included widgets.
  2
  3See the other GUI examples for more indepth information about specific widgets.
  4
  5If Arcade and Python are properly installed, you can run this example with:
  6python -m arcade.examples.gui.2_widgets
  7"""
  8
  9import textwrap
 10from copy import deepcopy
 11
 12import arcade
 13from arcade.gui import (
 14    NinePatchTexture,
 15    UIAnchorLayout,
 16    UIBoxLayout,
 17    UIButtonRow,
 18    UIDropdown,
 19    UIDummy,
 20    UIFlatButton,
 21    UIImage,
 22    UIInputText,
 23    UILabel,
 24    UIManager,
 25    UIMessageBox,
 26    UIOnActionEvent,
 27    UIOnChangeEvent,
 28    UISlider,
 29    UISpace,
 30    UISpriteWidget,
 31    UITextArea,
 32    UITextureButton,
 33    UITextureSlider,
 34    UITextureToggle,
 35    UIView,
 36)
 37from arcade.gui.experimental import UIPasswordInput
 38
 39# Load system fonts
 40arcade.resources.load_kenney_fonts()
 41
 42DEFAULT_FONT = ("Kenney Future", "arial")
 43DETAILS_FONT = ("arial", "Kenney Future Narrow")
 44
 45# Preload textures, because they are mostly used multiple times, so they are not
 46# loaded multiple times
 47TEX_SCROLL_DOWN = arcade.load_texture(":resources:gui_basic_assets/scroll/indicator_down.png")
 48TEX_SCROLL_UP = arcade.load_texture(":resources:gui_basic_assets/scroll/indicator_up.png")
 49
 50TEX_RED_BUTTON_NORMAL = arcade.load_texture(":resources:gui_basic_assets/button/red_normal.png")
 51TEX_RED_BUTTON_HOVER = arcade.load_texture(":resources:gui_basic_assets/button/red_hover.png")
 52TEX_RED_BUTTON_PRESS = arcade.load_texture(":resources:gui_basic_assets/button/red_press.png")
 53TEX_RED_BUTTON_DISABLE = arcade.load_texture(":resources:gui_basic_assets/button/red_disabled.png")
 54
 55TEX_TOGGLE_RED = arcade.load_texture(":resources:gui_basic_assets/toggle/red.png")
 56TEX_TOGGLE_GREEN = arcade.load_texture(":resources:gui_basic_assets/toggle/green.png")
 57
 58TEX_CHECKBOX_CHECKED = arcade.load_texture(":resources:gui_basic_assets/checkbox/blue_check.png")
 59TEX_CHECKBOX_UNCHECKED = arcade.load_texture(":resources:gui_basic_assets/checkbox/empty.png")
 60
 61TEX_SLIDER_THUMB_BLUE = arcade.load_texture(":resources:gui_basic_assets/slider/thumb_blue.png")
 62TEX_SLIDER_TRACK_BLUE = arcade.load_texture(":resources:gui_basic_assets/slider/track_blue.png")
 63TEX_SLIDER_THUMB_RED = arcade.load_texture(":resources:gui_basic_assets/slider/thumb_red.png")
 64TEX_SLIDER_TRACK_RED = arcade.load_texture(":resources:gui_basic_assets/slider/track_red.png")
 65TEX_SLIDER_THUMB_GREEN = arcade.load_texture(":resources:gui_basic_assets/slider/thumb_green.png")
 66TEX_SLIDER_TRACK_GREEN = arcade.load_texture(":resources:gui_basic_assets/slider/track_green.png")
 67
 68TEX_NINEPATCH_BASE = arcade.load_texture(":resources:gui_basic_assets/window/grey_panel.png")
 69
 70TEX_ARCADE_LOGO = arcade.load_texture(":resources:/logo.png")
 71
 72# Load animation for the sprite widget
 73frame_textures = []
 74for i in range(8):
 75    tex = arcade.load_texture(
 76        f":resources:images/animated_characters/female_adventurer/femaleAdventurer_walk{i}.png"
 77    )
 78    frame_textures.append(tex)
 79
 80TEX_ANIMATED_CHARACTER = arcade.TextureAnimation(
 81    [arcade.TextureKeyframe(frame) for frame in frame_textures]
 82)
 83
 84TEXT_WIDGET_EXPLANATION = textwrap.dedent("""
 85Arcade GUI provides three types of text widgets:
 86
 87
 88- {bold True}UILabel{bold False}:
 89A simple text widget that can be used to display text.
 90
 91- {bold True}UIInputText{bold False}:
 92A text widget that can be used to get text input from the user.
 93
 94- {bold True}UITextArea{bold False}:
 95A text widget that can be used to display text that is too long for a label.
 96
 97
 98This example shows how to use all three types of text widgets.
 99
100
101A few hints regarding the usage of the text widgets:
102
103
104{bold True}UILabel{bold False}:
105
106If you want to display frequently changing text,
107setting a background color will improve performance.
108
109
110{bold True}UIInputText{bold False}:
111
112UIInputText dispatches an event on_change, when the text changes.
113
114
115{bold True}UITextArea{bold False}:
116
117While the widget supports scrolling, there is no scrollbar provided yet.
118Users might oversee content.
119
120In addition UITextArea supports different text styles,
121which relate to Pyglet FormattedDocument.
122
123"PLAIN" - Plain text.
124
125"ATTRIBUTED" - Attributed text following the Pyglet attributed text style.
126
127"HTML" - Allows to use HTML tags for formatting.
128
129""").strip()
130
131
132class ScrollableTextArea(UITextArea, UIAnchorLayout):
133    """This widget is a text area that can be scrolled, like a UITextLayout, but shows indicator,
134    that the text can be scrolled."""
135
136    def __init__(self, **kwargs):
137        super().__init__(**kwargs)
138
139        indicator_size = 22
140        self._down_indicator = UIImage(
141            texture=TEX_SCROLL_DOWN, size_hint=None, width=indicator_size, height=indicator_size
142        )
143        self._down_indicator.visible = False
144        self.add(self._down_indicator, anchor_x="right", anchor_y="bottom", align_x=3)
145
146        self._up_indicator = UIImage(
147            texture=TEX_SCROLL_UP, size_hint=None, width=indicator_size, height=indicator_size
148        )
149        self._up_indicator.visible = False
150        self.add(self._up_indicator, anchor_x="right", anchor_y="top", align_x=3)
151
152    def on_update(self, dt):
153        self._up_indicator.visible = self.layout.view_y < 0
154        self._down_indicator.visible = (
155            abs(self.layout.view_y) < self.layout.content_height - self.layout.height
156        )
157
158
159class GalleryView(UIView):
160    def __init__(self):
161        super().__init__()
162        self.background_color = arcade.uicolor.BLUE_BELIZE_HOLE
163
164        root = self.add_widget(UIAnchorLayout())
165
166        # Setup side navigation
167        nav_side = UIButtonRow(vertical=True, size_hint=(0.3, 1))
168        nav_side.add(
169            UILabel(
170                "Categories",
171                font_name=DEFAULT_FONT,
172                font_size=32,
173                text_color=arcade.uicolor.DARK_BLUE_MIDNIGHT_BLUE,
174                size_hint=(1, 0.1),
175                align="center",
176            )
177        )
178        nav_side.add(UISpace(size_hint=(1, 0.01), color=arcade.uicolor.DARK_BLUE_MIDNIGHT_BLUE))
179
180        nav_side.with_padding(all=10)
181        nav_side.with_background(color=arcade.uicolor.WHITE_CLOUDS)
182        nav_side.add_button("Start", style=UIFlatButton.STYLE_BLUE, size_hint=(1, 0.1))
183        nav_side.add_button("Text", style=UIFlatButton.STYLE_BLUE, size_hint=(1, 0.1))
184        nav_side.add_button("Interactive", style=UIFlatButton.STYLE_BLUE, size_hint=(1, 0.1))
185        nav_side.add_button("Constructs", style=UIFlatButton.STYLE_BLUE, size_hint=(1, 0.1))
186        nav_side.add_button("Other", style=UIFlatButton.STYLE_BLUE, size_hint=(1, 0.1))
187        root.add(nav_side, anchor_x="left", anchor_y="top")
188
189        @nav_side.event("on_action")
190        def on_action(event: UIOnActionEvent):
191            if event.action == "Start":
192                self._show_start_widgets()
193            elif event.action == "Text":
194                self._show_text_widgets()
195            elif event.action == "Interactive":
196                self._show_interactive_widgets()
197            elif event.action == "Constructs":
198                self._show_construct_widgets()
199            elif event.action == "Other":
200                self._show_other_widgets()
201
202        # Setup content to show widgets in
203
204        self._body = UIAnchorLayout(size_hint=(0.7, 1))
205        self._body.with_padding(all=20)
206        root.add(self._body, anchor_x="right", anchor_y="top")
207
208        # init start widgets
209        self._show_start_widgets()
210
211    def _show_start_widgets(self):
212        """Show a short introduction message."""
213        self._body.clear()
214        self._body.add(
215            UITextArea(
216                text=textwrap.dedent("""
217                Welcome to the Widget Gallery
218
219                Choose a category on the left to see the widgets.
220                You can checkout the source code in the examples/gui folder
221                to see how this gallery is built.
222                """).strip(),
223                font_name=DETAILS_FONT,
224                font_size=32,
225                text_color=arcade.uicolor.WHITE,
226                size_hint=(0.8, 0.8),
227            ),
228            anchor_y="top",
229        )
230        open_sourcecode = self._body.add(
231            UIFlatButton(
232                text="Open Source Code", style=UIFlatButton.STYLE_RED, size_hint=(0.3, 0.1)
233            ),
234            anchor_y="bottom",
235            align_y=20,
236        )
237
238        @open_sourcecode.event("on_click")
239        def on_click(_):
240            """This will open the source code of this example on GitHub."""
241            import webbrowser
242
243            webbrowser.open(
244                "https://github.com/pythonarcade/arcade/tree/development/arcade/examples/gui"
245            )
246
247    def _show_text_widgets(self):
248        """Show the text widgets.
249
250        For this we clear the body and add the text widgets.
251
252        Featuring:
253        - UILabel
254        - UIInputText
255        - UITextArea
256        """
257
258        self._body.clear()
259
260        box = UIBoxLayout(vertical=True, size_hint=(1, 1), align="left", space_between=10)
261        self._body.add(box)
262        box.add(UILabel("Text Widgets", font_name=DEFAULT_FONT, font_size=32))
263        box.add(UISpace(size_hint=(1, 0.1)))
264
265        row_1 = UIBoxLayout(vertical=False, size_hint=(1, 0.1))
266        box.add(row_1)
267        row_1.add(UILabel("Username: ", font_name=DEFAULT_FONT, font_size=24))
268        name_input = row_1.add(
269            UIInputText(
270                width=400,
271                height=40,
272                font_name=DEFAULT_FONT,
273                font_size=24,
274                border_color=arcade.uicolor.GRAY_CONCRETE,
275                border_width=2,
276            )
277        )
278
279        row_2 = UIBoxLayout(vertical=False, size_hint=(1, 0.1))
280        box.add(row_2)
281        row_2.add(UILabel("Password: ", font_name=DEFAULT_FONT, font_size=24))
282        pw_input = row_2.add(
283            UIPasswordInput(
284                width=400,
285                height=40,
286                font_name=DEFAULT_FONT,
287                font_size=24,
288                border_color=arcade.uicolor.GRAY_CONCRETE,
289                border_width=2,
290            )
291        )
292
293        @pw_input.event("on_change")
294        def _(event: UIOnChangeEvent):
295            event.source.invalid = event.new_value != "arcade"
296
297        welcome_label = box.add(
298            UILabel("Nice to meet you ''", font_name=DEFAULT_FONT, font_size=24)
299        )
300
301        @name_input.event("on_change")
302        def _(event: UIOnChangeEvent):
303            welcome_label.text = f"Nice to meet you `{event.new_value}`"
304
305        box.add(UISpace(size_hint=(1, 0.3)))  # Fill some of the left space
306
307        text_area = box.add(
308            ScrollableTextArea(
309                text=TEXT_WIDGET_EXPLANATION,
310                size_hint=(1, 0.9),
311                font_name=DETAILS_FONT,
312                font_size=16,
313                text_color=arcade.uicolor.WHITE,
314                document_mode="ATTRIBUTED",
315            )
316        )
317        text_area.with_padding(left=10, right=10)
318        text_area.with_border(color=arcade.uicolor.GRAY_CONCRETE, width=2)
319
320    def _show_interactive_widgets(self):
321        self._body.clear()
322        box = UIBoxLayout(vertical=True, size_hint=(1, 1), align="left", space_between=10)
323        self._body.add(box)
324        box.add(UILabel("Interactive Widgets", font_name=DEFAULT_FONT, font_size=32))
325        box.add(UISpace(size_hint=(1, 0.1)))
326
327        flat_row = UIBoxLayout(vertical=False, size_hint=(1, 0.1), space_between=10)
328        box.add(flat_row)
329
330        flat_row.add(
331            UIFlatButton(
332                text="UIFlatButton blue", style=UIFlatButton.STYLE_BLUE, size_hint=(0.3, 1)
333            )
334        )
335        flat_row.add(
336            UIFlatButton(text="UIFlatButton red", style=UIFlatButton.STYLE_RED, size_hint=(0.3, 1))
337        )
338        flat_row.add(
339            UIFlatButton(text="disabled", style=UIFlatButton.STYLE_BLUE, size_hint=(0.3, 1))
340        ).disabled = True
341
342        tex_row = UIBoxLayout(vertical=False, size_hint=(1, 0.1), space_between=10)
343        box.add(tex_row)
344        tex_row.add(
345            UITextureButton(
346                text="UITextureButton",
347                texture=TEX_RED_BUTTON_NORMAL,
348                texture_hovered=TEX_RED_BUTTON_HOVER,
349                texture_pressed=TEX_RED_BUTTON_PRESS,
350                texture_disabled=TEX_RED_BUTTON_DISABLE,
351                size_hint=(0.3, 1),
352            )
353        )
354
355        tex_row.add(UISpace(size_hint=(0.3, 1)))
356
357        tex_row.add(
358            UITextureButton(
359                text="disabled",
360                texture=TEX_RED_BUTTON_NORMAL,
361                texture_hovered=TEX_RED_BUTTON_HOVER,
362                texture_pressed=TEX_RED_BUTTON_PRESS,
363                texture_disabled=TEX_RED_BUTTON_DISABLE,
364                size_hint=(0.3, 1),
365            )
366        ).disabled = True
367
368        toggle_row = UIBoxLayout(vertical=False, size_hint=(1, 0.1), space_between=10)
369        box.add(toggle_row)
370        toggle_row.add(
371            UILabel("UITextureToggle", font_name=DETAILS_FONT, font_size=16, size_hint=(0.3, 0))
372        )
373        toggle_row.add(
374            UITextureToggle(
375                on_texture=TEX_TOGGLE_RED,
376                off_texture=TEX_TOGGLE_GREEN,
377                width=64,
378                height=32,
379            )
380        )
381        toggle_row.add(
382            UITextureToggle(
383                on_texture=TEX_CHECKBOX_CHECKED,
384                off_texture=TEX_CHECKBOX_UNCHECKED,
385                width=32,
386                height=32,
387            )
388        )
389
390        dropdown_row = UIBoxLayout(vertical=False, size_hint=(1, 0.1), space_between=10)
391        box.add(dropdown_row)
392        dropdown_row.add(
393            UILabel("UIDropdown", font_name=DETAILS_FONT, font_size=16, size_hint=(0.3, 0))
394        )
395        dropdown_row.add(
396            UIDropdown(
397                default="Option 1",
398                options=["Option 1", "Option 2", "Option 3"],
399            )
400        )
401
402        slider_row = UIBoxLayout(vertical=False, size_hint=(1, 0.1), space_between=10)
403        box.add(slider_row)
404
405        slider_row.add(
406            UILabel(
407                "UISlider",
408                font_name=DETAILS_FONT,
409                font_size=16,
410                size_hint=(0.3, 0),
411            )
412        )
413        s1 = slider_row.add(UISlider(size_hint=(0.3, 1), step=1, style=UISlider.NO_STEP_STYLE))
414        s2 = slider_row.add(
415            UISlider(
416                size_hint=(0.3, 1),
417                step=5,
418            )
419        )
420        s3 = slider_row.add(
421            UISlider(
422                size_hint=(0.3, 1),
423                step=10,
424            )
425        )
426
427        @s1.event("on_change")
428        def _(event: UIOnChangeEvent):
429            s2.value = event.new_value
430            s3.value = event.new_value
431
432        @s2.event("on_change")
433        def _(event: UIOnChangeEvent):
434            s1.value = event.new_value
435            s3.value = event.new_value
436
437        @s3.event("on_change")
438        def _(event: UIOnChangeEvent):
439            s1.value = event.new_value
440            s2.value = event.new_value
441
442        tex_slider_row = UIBoxLayout(vertical=False, size_hint=(1, 0.1), space_between=10)
443        box.add(tex_slider_row)
444
445        tex_slider_row.add(
446            UILabel(
447                "UITextureSlider",
448                font_name=DETAILS_FONT,
449                font_size=16,
450                size_hint=(0.3, 0),
451            )
452        )
453
454        ts1 = tex_slider_row.add(
455            UITextureSlider(
456                thumb_texture=TEX_SLIDER_THUMB_BLUE,
457                track_texture=NinePatchTexture(10, 10, 10, 10, TEX_SLIDER_TRACK_BLUE),
458                size_hint=(0.3, None),
459            )
460        )
461
462        green_style = deepcopy(UITextureSlider.DEFAULT_STYLE)
463        green_style["normal"].filled_track = arcade.uicolor.GREEN_GREEN_SEA
464        green_style["hover"].filled_track = arcade.uicolor.GREEN_EMERALD
465        green_style["press"].filled_track = arcade.uicolor.GREEN_GREEN_SEA
466        ts2 = tex_slider_row.add(
467            UITextureSlider(
468                thumb_texture=TEX_SLIDER_THUMB_GREEN,
469                track_texture=NinePatchTexture(10, 10, 10, 10, TEX_SLIDER_TRACK_GREEN),
470                size_hint=(0.3, None),
471                style=green_style,
472            )
473        )
474
475        red_style = deepcopy(UITextureSlider.DEFAULT_STYLE)
476        red_style["normal"].filled_track = arcade.uicolor.RED_POMEGRANATE
477        red_style["hover"].filled_track = arcade.uicolor.RED_ALIZARIN
478        red_style["press"].filled_track = arcade.uicolor.RED_POMEGRANATE
479        ts3 = tex_slider_row.add(
480            UITextureSlider(
481                thumb_texture=TEX_SLIDER_THUMB_RED,
482                track_texture=NinePatchTexture(10, 10, 10, 10, TEX_SLIDER_TRACK_RED),
483                size_hint=(0.3, None),
484                style=red_style,
485            )
486        )
487
488        @ts1.event("on_change")
489        def _(event: UIOnChangeEvent):
490            ts2.value = event.new_value
491            ts3.value = event.new_value
492
493        @ts2.event("on_change")
494        def _(event: UIOnChangeEvent):
495            ts1.value = event.new_value
496            ts3.value = event.new_value
497
498        @ts3.event("on_change")
499        def _(event: UIOnChangeEvent):
500            ts1.value = event.new_value
501            ts2.value = event.new_value
502
503        box.add(UISpace(size_hint=(0.2, 0.1)))
504        text_area = box.add(
505            UITextArea(
506                text=textwrap.dedent("""
507                        Interactive widgets are widgets that the user can interact with.
508                        This includes buttons, toggles, sliders and more.
509
510                        By subclassing UIInteractiveWidget you
511                        can create your own interactive widgets.
512
513                        For text input have a look at the text widgets.
514                    """).strip(),
515                font_name=DETAILS_FONT,
516                font_size=16,
517                text_color=arcade.uicolor.WHITE,
518                size_hint=(1, 0.9),
519            )
520        )
521        text_area.with_padding(left=10, right=10)
522        text_area.with_border(color=arcade.uicolor.GRAY_CONCRETE, width=2)
523
524    def _show_construct_widgets(self):
525        self._body.clear()
526        box = UIBoxLayout(vertical=True, size_hint=(1, 1), align="left", space_between=10)
527        self._body.add(box)
528        box.add(UILabel("Constructs", font_name=DEFAULT_FONT, font_size=32))
529        box.add(UISpace(size_hint=(1, 0.1)))
530
531        message_row = UIBoxLayout(vertical=False, size_hint=(1, 0.1), space_between=10)
532        box.add(message_row)
533        message_row.add(
534            UILabel(
535                "UIMessageBox",
536                font_name=DETAILS_FONT,
537                font_size=16,
538                size_hint=(0.3, 0),
539            )
540        )
541        message_button = message_row.add(
542            UIFlatButton(
543                text="Show Message",
544                style=UIFlatButton.STYLE_BLUE,
545                size_hint=(0.3, 1),
546            )
547        )
548
549        @message_button.event("on_click")
550        def on_click(event):
551            self.ui.add(
552                UIMessageBox(
553                    width=500,
554                    height=350,
555                    title="Message Box",
556                    buttons=("Ok", "Cancel"),
557                    message_text=textwrap.dedent("""
558                    This is a message box.
559                    It can be used to show messages to the user.
560
561                    You can add buttons to it, to let the user choose an action.
562                    """).strip(),
563                ),
564                layer=UIManager.OVERLAY_LAYER,
565            )
566
567        button_row = UIBoxLayout(vertical=False, size_hint=(1, 0.1), space_between=10)
568        box.add(button_row)
569        button_row.add(
570            UILabel(
571                "UIButtonRow",
572                font_name=DETAILS_FONT,
573                font_size=16,
574                size_hint=(0.3, 0),
575            )
576        )
577        buttons = button_row.add(
578            UIButtonRow(
579                text="Show Message",
580                style=UIFlatButton.STYLE_BLUE,
581                size_hint=(1, 0),
582            )
583        )
584        buttons.add_button("Default Style", size_hint=(1, None))
585        buttons.add_button("Red Style", style=UIFlatButton.STYLE_RED, size_hint=(1, None))
586        buttons.add_button("Blue Style", style=UIFlatButton.STYLE_BLUE, size_hint=(1, None))
587
588        # Constructs
589        # "UIButtonRow",
590
591        box.add(UISpace(size_hint=(0.2, 0.1)))
592        text_area = box.add(
593            UITextArea(
594                text=textwrap.dedent("""
595            Constructs are widgets that combine multiple widgets, to provide common functionality
596            within a simple widget.
597            Examples for this are message boxes or rows of buttons.
598            """).strip(),
599                font_name=DETAILS_FONT,
600                font_size=16,
601                text_color=arcade.uicolor.WHITE,
602                size_hint=(1, 0.5),
603            )
604        )
605        text_area.with_padding(left=10, right=10)
606        text_area.with_border(color=arcade.uicolor.GRAY_CONCRETE, width=2)
607
608    def _show_other_widgets(self):
609        self._body.clear()
610        box = UIBoxLayout(vertical=True, size_hint=(1, 1), align="left", space_between=10)
611        self._body.add(box)
612        box.add(UILabel("Other Widgets", font_name=DEFAULT_FONT, font_size=32))
613        box.add(UISpace(size_hint=(1, 0.1)))
614
615        image_row = box.add(UIBoxLayout(vertical=False, size_hint=(1, 0.1)))
616        image_row.add(UILabel("UIImage", font_name=DETAILS_FONT, font_size=16, size_hint=(0.3, 0)))
617        image_row.add(UIImage(texture=TEX_ARCADE_LOGO, width=64, height=64))
618
619        dummy_row = box.add(UIBoxLayout(vertical=False, size_hint=(1, 0.1)))
620        dummy_row.add(UILabel("UIDummy", font_name=DETAILS_FONT, font_size=16, size_hint=(0.3, 0)))
621        dummy_row.add(UIDummy(size_hint=(0.2, 1)))
622        dummy_row.add(UIDummy(size_hint=(0.2, 1)))
623        dummy_row.add(UIDummy(size_hint=(0.2, 1)))
624
625        sprite = arcade.TextureAnimationSprite(animation=TEX_ANIMATED_CHARACTER)
626        sprite.scale = 0.5
627        sprite_row = box.add(UIBoxLayout(vertical=False, size_hint=(1, 0.1)))
628        sprite_row.add(
629            UILabel("UISpriteWidget", font_name=DETAILS_FONT, font_size=16, size_hint=(0.3, 0))
630        )
631        sprite_row.add(UISpriteWidget(sprite=sprite, width=sprite.width, height=sprite.height))
632
633        box.add(UISpace(size_hint=(0.2, 0.1)))
634        text_area = box.add(
635            UITextArea(
636                text=textwrap.dedent("""
637                    Arcade GUI provides also a few more widgets for special use cases.
638
639                    - UIImage: A widget to display an image.
640                    - UIDummy: Which can be used as a placeholder.
641                                It renders a random color and changes it on click.
642                    - UISpace: A widget that only takes up space.
643                                But can also be used to add a colored space.
644                    - UISpriteWidget: A widget that can display a sprite.
645
646                    """).strip(),
647                font_name=DETAILS_FONT,
648                font_size=16,
649                text_color=arcade.uicolor.WHITE,
650                size_hint=(1, 0.9),
651            )
652        )
653        text_area.with_padding(left=10, right=10)
654        text_area.with_border(color=arcade.uicolor.GRAY_CONCRETE, width=2)
655
656
657def main():
658    window = arcade.Window(title="GUI Example: Widget Gallery")
659    window.show_view(GalleryView())
660    window.run()
661
662
663if __name__ == "__main__":
664    main()

© Copyright 2025, Paul Vincent Craven.

Built with Sphinx using a theme provided by Read the Docs.