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

© Copyright 2024, Paul Vincent Craven.

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