1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
"""User interface examples."""
import sys
import sdl2
import sdl2.ext
# Define some global color constants
WHITE = sdl2.ext.Color(255, 255, 255)
GREY = sdl2.ext.Color(200, 200, 200)
RED = sdl2.ext.Color(255, 0, 0)
GREEN = sdl2.ext.Color(0, 255, 0)
# Create a resource, so we have easy access to the example images.
RESOURCES = sdl2.ext.Resources(__file__, "resources")
# A callback for the Button.motion event.
def onmotion(button, event):
print("Mouse moves over the button!")
# A callback for the Button.click event.
def onclick(button, event):
print("Button was clicked!")
# A callback for the TextEntry.input event.
def oninput(entry, event):
print("Input received with text '%s'" % event.text.text)
print("Text on the entry now is '%s'" % entry.text)
# A callback for the TextEntry.edit event.
def onedit(entry, event):
print("Edit received with text '%s', start '%d', length '%d'" %
(event.edit.text, event.edit.start, event.edit.length))
def oncheck(button, event):
if button.checked:
color = GREEN
else:
color = RED
if button.factory.sprite_type == sdl2.ext.SOFTWARE:
sdl2.ext.fill(button.surface, color)
else:
# SDL textures do not support color manipulation operation as easy
# as software surface (since the texture is ideally stored somwhere
# on the GPU memory in a GPU-specific layout [or not]). To circumvent
# this, we create a temporary sprite (texture) and exchange the button
# texture with it.
tmpsprite = button.factory.from_color(color, button.size)
button.texture, tmpsprite.texture = tmpsprite.texture, button.texture
del tmpsprite
def run():
# You know those from the helloworld.py example.
# Initialize the video subsystem, create a window and make it visible.
sdl2.ext.init()
window = sdl2.ext.Window("UI Elements", size=(800, 600))
window.show()
# Create a sprite factory that allows us to create visible 2D elements
# easily. Depending on what the user chosses, we either create a factory
# that supports hardware-accelerated sprites or software-based ones.
# The hardware-accelerated SpriteFactory requres a rendering context
# (or SDL_Renderer), which will create the underlying textures for us.
if "-hardware" in sys.argv:
print("Using hardware acceleration")
renderer = sdl2.ext.Renderer(window, flags=sdl2.render.SDL_RENDERER_ACCELERATED)
factory = sdl2.ext.SpriteFactory(sdl2.ext.TEXTURE, renderer=renderer)
else:
print("Using software rendering")
renderer = sdl2.ext.Renderer(window, flags=sdl2.render.SDL_RENDERER_SOFTWARE)
factory = sdl2.ext.SpriteFactory(sdl2.ext.SOFTWARE)
# Create a UI factory, which will handle several defaults for
# us. Also, the UIFactory can utilises software-based UI elements as
# well as hardware-accelerated ones; this allows us to keep the UI
# creation code clean.
uifactory = sdl2.ext.UIFactory(factory)
# Create a simple Button sprite, which reacts on mouse movements and
# button presses and fill it with a white color. All UI elements
# inherit directly from the TextureSprite (for TEXTURE) or SoftwareSprite
# (for SOFTWARE), so everything you can do with those classes is also
# possible for the UI elements.
button = uifactory.from_image(sdl2.ext.BUTTON,
RESOURCES.get_path("button.bmp"))
button.position = 50, 50
# Create a TextEntry sprite, which reacts on keyboard presses and
# text input.
entry = uifactory.from_image(sdl2.ext.TEXTENTRY,
RESOURCES.get_path("textentry.bmp"))
entry.position = 50, 200
# Create a CheckButton sprite. The CheckButton is a specialised
# Button, which can switch its state, identified by the 'checked'
# attribute by clicking.
checkbutton = uifactory.from_color(sdl2.ext.CHECKBUTTON, RED, size=(50, 50))
checkbutton.position = 200, 50
# Bind some actions to the button's event handlers. Whenever a click
# (combination of a mouse button press and mouse button release), the
# onclick() function will be called.
# Whenever the mouse moves around in the area occupied by the button, the
# onmotion() function will be called.
# The event handlers receive the issuer of the event as first argument
# (the button is the issuer of that event) and the SDL event data as second
# argument for further processing, if necessary.
button.click += onclick
button.motion += onmotion
# Bind some actions to the entry's event handlers. The TextEntry
# receives input events, once it has been activated by a mouse
# button press on its designated area. The UIProcessor class takes
# care of this internally through its activate() method. If the
# TextEntry is activated, SDL_TEXTINPUT events are enabled by the
# relevant SDL2 functions, causing input events to occur, that are
# handled by the TextEntry.
entry.input += oninput
entry.editing += onedit
checkbutton.click += oncheck
checkbutton.factory = factory
# Since all gui elements are sprites, we can use the
# SpriteRenderSystem class, we learned about in helloworld.py, to
# draw them on the Window.
spriterenderer = factory.create_sprite_render_system(window)
# Create a new UIProcessor, which will handle the user input events
# and pass them on to the relevant user interface elements.
uiprocessor = sdl2.ext.UIProcessor()
running = True
while running:
events = sdl2.ext.get_events()
for event in events:
if event.type == sdl2.SDL_QUIT:
running = False
break
# Pass the SDL2 events to the UIProcessor, which takes care of
# the user interface logic.
uiprocessor.dispatch([button, checkbutton, entry], event)
renderer.clear(0)
# Render all user interface elements on the window.
spriterenderer.render((button, entry, checkbutton))
sdl2.ext.quit()
return 0
if __name__ == "__main__":
sys.exit(run())
|