156 lines
5.9 KiB
Python
156 lines
5.9 KiB
Python
"""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)
|
|
factory = sdl2.ext.SpriteFactory(sdl2.ext.TEXTURE, renderer=renderer)
|
|
else:
|
|
print("Using software rendering")
|
|
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)
|
|
|
|
# Render all user interface elements on the window.
|
|
spriterenderer.render((button, entry, checkbutton))
|
|
|
|
sdl2.ext.quit()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(run())
|