basic single-window xcs349/s20/slides/11...javafx has a rich event class, with several specific...
TRANSCRIPT
Events
Event-driven programming
Event loop
Event dispatch
Event handling
Event Driven Programming
2
Event-driven programming is a programming paradigm that
bases program execution flow on events. These can represent
user actions or other triggers in the system.
User Interactive System
express
present perceive
translat
e
seconds milliseconds
or faster
Event
3
English:
- An observable occurrence, often extraordinary occurrence
User Interface Architecture:
- An event is a a message to notify an application that something
happened
- A message of interest to an interface.
Events can be initiated by a user e.g. mouse, or the system e.g. timer
Examples (exact event name will vary by toolkit):
- Keyboard (key press, key release)
- Pointer Events (button press, button release, mouse move)
- Window crossing (mouse enter, mouse leave)
- Input focus (focus gained, focus lost)
- Window events (window exposed, window destroy, window minimize)
- Timer events (tick)
Why Event Driven Programming?
4
The system is designed to be responsive to events.
This allows us to prioritize user-initiated actions, and carefully prioritize
work while remaining responsive to a user.
Foreground Events
- Events initiated by the user
- Created as a result of the user interacting with the user interface
Background Events
- Events generated by the system
- May be received and processed by the user interface.
What does an event look like?
5
Events are just messages representing something of interest.
JavaFX has a rich Event class, with several specific event types.
All event classes include the following fields:
- EventType Type of the event that occurred e.g. KEY_EVENT
- Source Origin of the event (previous node in the scene graph)
- Target Node on which the event occurred (for user events)
- Consumed Whether this event has been processed
Events also include fields specific to their subtype.
- e.g. MouseEvent will contain a Point representing the mouse coordinates.
Event Subclasses
6
The following event subclasses are commonly used.
MouseEvent − This is an input event that occurs when a mouse is
manipulated. It includes actions like mouse clicked, mouse pressed,
mouse released, mouse moved, mouse entered target, mouse exited
target, etc.
KeyEvent − This is an input event that indicates the key stroke
occurred on a node. This event includes actions like key pressed, key
released and key typed.
DragEvent − This is an input event which occurs when the mouse is
dragged. It includes actions like drag entered, drag dropped, drag
entered target, drag exited target, drag over, etc.
WindowEvent − This is an event related to window showing/hiding
actions. It includes actions like window hiding, window shown,
window hidden, window showing, etc. https://www.tutorialspoint.com/javafx/javafx_event_handling.htm
7
MouseEvents.java
KeyEventDemo.java
Java Event Type Hierarchy
8
How does the windowing system manage events?
9
The Windowing System needs to package events and pass them to the
appropriate application toolkit (e.g. as Java events).
It performs these steps:
1. Collect event information from user action, or underlying hardware
2. Put relevant information in a known event structure
3. Order the events, by time, in a queue
4. Deliver the events from the queue to the correct application
Event Architecture
This can be modelled as a pipeline:
Capture and Queue low-level hardware events,
Dispatch events to the correct window, and
Handle each event within the application
10
Event Capture
Event Queue
Event Dispatch
Event Handling
Event Loop
11
The windowing system uses an event loop to continuously check for new
events.
It iterates through the system event queue, and dispatches events to the
correct application.
This can be either the application which triggered the event, or the
window in the foreground that is intercepting events.
// windowing system event loop while get next event determine which window gets the event dispatch event to the window loop
Event Loop
The application will sometimes have its own event loop and secondary
event queue, to accumulate events until it is ready to handle them.
e.g. XWindows need to be written to pull events from this local event
queue.
12
// XWindows application event loop while get next event from windowing system handle the event: if the event was a quit message exit the loop else do something based on the type of event draw to the screen loop
Xwindows Event Loop eventloop.min.cpp
13
// select which events to monitor XSelectInput(dis, win, PointerMotionMask | KeyPressMask); ... XEvent event; // save the event here while(true) { // loop until we explicitly stop XNextEvent( display, &event ); // block waiting for an event switch( event.type ) { // one event class (unusual!) case MotionNotify: // handle mouse movement event // handle here … break; case KeyPress: // handle key press event // handle here … exit(0); // exit event loop break; } }
Java Event Loop
14
The Windowing System delivers to the application, then the JVM takes over. Java applications rely on the JVM to queue, manage and dispatch events for each running application. The JRE has an event-handling thread that • pulls events from the JVM event queue • formats them into Java events, and • passes them to the application code to process.
// JRE event loop (implicit) while get next event handle the event: package as Java event pass to the application (to do something with it) loop
This is the point
at which events
are handed off
to the
application
Event Dispatch
View Hierarchy
Lightweight vs. Heavyweight
Positional Dispatch
Focus Dispatch
Event Dispatch
16
Let’s talk about events being delivered within the
application window.
We want the event to eventually get dispatched to
the Node that is responsible for initiating the
event.
e.g. if you click a button on a form, we want that
button to receive and process the MouseEvent.
e.g. if you build a drawing app and click on a
circle to select it, the circle class should receive
the corresponding MouseEvent. If you then drag
it, it should receive anotehr MouseEvent
representing the drag itself.
View Hierarchy
2D layout of widgets forms scene
graph.
Container widgets are the ancestors of
simple widgets
Dispatching an event to a specific
widget is done by traversing this
hierarchy
17
Heavyweight Widgets
Underlying platform provides widgets and hierarchical “windowing” system
Widget toolkit wraps platform widgets for programming language
The platform (ex. BWS) can dispatch events to a specific widget
Examples: Java’s AWT, OSX Cocoa, Windows MFC, nested X Windows, standard HTML form widgets
Advantages
Events generated by user are passed directly to components by the Platform
Preserves Platform look and feel
Disadvantages
Platform-specific programming
Multi-platform toolkits tend to be defined as the “lowest-common set” of components
18
Heavyweight Dispatch
19
WS dispatch to
button click on
button
Most toolkits don’t
work like this. JavaFX
is lightweight (see next
slides!)
Lightweight Widgets
OS provides a top level window
Widget toolkit draws its own widgets in the window.
Toolkit is responsible for mapping events to their corresponding widgets
Examples: Java Swing, JQuery UI, Windows WPF
Advantages
Can guarantee identical look-and-feel across platforms.
Can guarantee consistent widget set on all platforms.
Can implement very light/optimized widgets.
Disadvantages
Concerns that they appear “non-native”.
Concerns about performance with extra layer of abstraction.
20
Lightweight Dispatch
21
toolkit or
application
dispatches
to button
click on
button
BWS dispatch
to window
This is a more modern
approach, that works
with self-contained
toolkits – like Java FX.
Dispatching Events in Java FX
22
The event dispatch process contains the following steps:
- Target selection Determine which node should receive the
event
- Route construction Calculate a path through graph to this node
- Event capturing Traverse the path DOWN from Root to Node
- Event bubbling Traverse the path back UP from Node to Root
Scene graph. Clicking on Triangle
will generate a MouseClicked event
that will need to be dispatched to
the triangle instance to handle.
Target & Route Selection
23
Target Selection is determined by the type of Event.
For key events, the target is the node that has focus.
For mouse events, the target is the node at the location of the cursor.
For continuous gesture events that are generated by a gesture on a
touch screen, the target is the node at the center point of all touches at
the beginning of the gesture.
For swipe events that are generated by a swipe on a touch screen, the
target is the node at the center of the entire path of all of the fingers.
For touch events, the default target for each touch point is the node at
the location first pressed.
Route Selection is the path to a particular Node through the tree.
Stored as chain, using the Source and Target fields of the event.
Capture & Bubble Phases
24
JavaFX supports both top-down and bottom-up capture.
Events propagate from the Root to the Target (“Capture phase”), then
back up to the Root (“Bubble phase”).
Any Node in the path can intercept (“consume”) the Event, or either
pass.
The Capture
phase walks
down the tree
from the Stage
(root) through
each Node
until it reaches
the Triangle.
The Bubble
phase walks
up the tree
from the
Triangle,
through each
Node until it
reaches the
Stage (Root)
Processing Events
25
All nodes in the path can choose to intercept and process an event
- Capture phase: Nodes can use an Event Filter to intercept the
event.
- Bubble phase: Nodes can use a Handler to intercept the event.
All nodes that register to receive an event will have a chance to
process it!
Capture phase Bubble phase
Why do we require this level of processing?
27
Sending events to the Node under the
cursor is called positional dispatch.
However, widgets on the screen can
overlap (parent + node in the tree).
When this happens, who takes
responsibility for processing the event?
Two main approaches that we’ll
consider:
- Bottom-up dispatch (Bubble phase)
- Top-down dispatch (Capture phase)
Bottom-up Positional Dispatch (using Bubble phase)
Lowest-level node is given the first chance to handle the event
Event is dispatched to leaf node widget in the UI tree that contains
the mouse cursor (using a Handler, registered at the Node for that
event)
- The leaf node is expected to process the event first
- The parent node can optionally process during the bubble phase
(since we bubble up from the leaf to the root of the tree).
28
Parent Processing
Why would the parent Node need to process the event?
- e.g. A palette of colour swatches may implement the colours as
buttons. But palette needs to track the currently selected colour.
Easiest if the palette deals with the events.
- See sample code for an example of passing a request to a parent
widget
- e.g. events/java/radiobuttons/RadioButtonDemo.java
29
Top-down Positional Dispatch (using Capture phase)
Event is dispatched to widget in the highest level node in the UI tree,
which has the first chance to handle the event
- i.e. typically attaches a Filter to intercept the event before the target.
It can consume the event, or let it continue to the Target node (during
the Capture phase).
30
This is useful for example, when a parent wishes to disable it’s children.
Positional Dispatch Limitations
Positional dispatch can lead to odd behaviour:
- Mouse drag starts in a scrollbar, but then moves outside the
scrollbar: send the events to the adjacent widget?
- Mouse press event in one button widget but release is in another:
each button gets one of the events?
Sometimes position isn’t enough, also need to consider which widget
is “in focus”
31
Focus Dispatch
Events dispatched to widget regardless of mouse cursor position
Needed for all keyboard and some mouse events:
- Keyboard focus: Click on text field, move cursor off, start typing
- Mouse focus: Mouse down on button, move off, mouse up … also
called “mouse capture”
Maximum one keyboard focus and one mouse focus
- why?
Need to gain and lose focus at appropriate times
- Transfer focus on mouse down (“capture”)
• So focus dispatch need positional dispatch too!
- Transfer focus when TAB key is pressed
32
Event Handling
Event Filters
Event Handlers
Generic vs. Specialized Events
Event Architecture
This can be modelled as a pipeline:
Capture and Queue low-level hardware events,
Dispatch events to the correct window and widget
Handle events by binding them to the correct code to execute.
37
Event Capture
Event Queue
Event Dispatch
Event Handling
Event-to-Code Binding
38
How do we design our GUI architecture to route events to the correct
target?
Design Goals of Event Handling Mechanisms:
- Easy to understand (clear connection between event and code)
- Easy to implement (binding paradigm or API)
- Easy to debug (how did this event get here?)
- Good performance
We’ll walkthrough some common implementations of event-binding.
1. Switch Statement Binding (X11)
39
All events consumed in one event loop in the application (not by
widgets)
- Switch selects window and code to handle the event
- An event is a generic structure with a few common fields.
Used in Xlib and many early systems while( true ) { XNextEvent(display, &event); // wait next event switch(event.type) { case Expose: // ... handle expose event ... cout << event.xexpose.count << endl; break; case ButtonPress: // ... handle button press event ... cout << event.xbutton.x << endl; break; ...
Switch-Statement Binding Problems
41
Difficult to maintain
- Dozens of different types of events that need to be managed
Events are not delegated to a class that is responsible for them
- Leads to code where events are handled in the loop itself
- Ideally, we would prefer if the GUI widgets handled the events.
- e.g. if a user clicks on a widget, we want the mouse_click event to
be passed back to that widget to be interpreted and processed.
2. Inheritance Binding (Early Java)
42
Event is dispatched to a generic Object-Oriented (OO) widget
- OO widget derived from an abstract base class with all event
handling methods defined within that base class
e.g. Widget class methods for onMousePress, onMouseMove…
- The derived widget class has to override the event methods
- Each method handles multiple related events
Used in Java 1.0
InheritanceEvents.java
43
public class InheritanceEvents extends JPanel { public static void main(String[] args) { InheritanceEvents p = new InheritanceEvents(); ... // enable events for this JPanel p.enableEvents(MouseEvent.MOUSE_MOTION_EVENT_MASK); } protected void processMouseMotionEvent(MouseEvent e) { // only detects button state WHILE moving! if (e.getID() == MouseEvent.MOUSE_DRAGGED) { x = e.getX(); y = e.getY(); repaint(); } }
Inheritance Problems
44
Multiple event types are processed through each event method
- complex and error-prone
- still a switch statement, but in the widget instead of some other
method
No filtering of events
- performance issues
- consider frequent events like mouse_move – maybe we don’t want
them all to be delivered?
It doesn’t scale well: need to modify the base class to add new event
types
- e.g. penButtonPress, touchGesture, ….
Muddies separation between GUI and application logic
- Event handling application code is in the inherited widget
- Use inheritance for extending functionality, not binding events
3. Listener Model (Current Java)
45
Define interfaces for specific event types (or device types)
- e.g. MouseListener, MouseMotionListener, KeyListener,
WindowListener, …
You write a class that implements the interface for the events that you
want to handle. e.g. KeyListener for keyboard events
When event is dispatched, relevant listener method is called for that
widget
- mousePressed, mouseMoved, …
Recall: Capture & Bubble Phases
46
Events propagate from the Root to the Target (“Capture phase”), then
back up to the Root (“Bubble phase”).
Any Node in the path can intercept (“consume”) the Event, on either
pass.
The Capture
phase walks
down the tree
from the Stage
(root) through
each Node
until it reaches
the Triangle.
The Bubble
phase walks
up the tree
from the
Triangle,
through each
Node until it
reaches the
Stage (Root)
Event Handling
48
Define an EventHandler, and override the handle() method for the event type that you care about managing.
- Both Event Filters and Handlers use the same EventHandler class.
Add to a specific Node either using the EventFilter or EventHandler methods.
EventHandler1.java
Convenience Classes
49
Even better – replace with anonymous classes.
Even better – use convenience classes built-in to the Nodes (for handlers).
EventHandler1.java
EventHandler3.java
Other events that you may encounter
50
ActionListener
There’s also a default listener: ActionListener
This represents the default activation of a widget.
- e.g. pressing a button, selecting an item in a combo-box.
- There are often setActionListener() methods that let you set and
catch generic events.
WindowListener
You can attach WindowListeners to catch events related to
manipulating windows.
Propagated from the Windowing System to the application.
Useful for catching windows being resized, closed etc.
Exceptions to the Rules
There’s always exceptions….
Bypassing Event Dispatch: Global Event Queue “Hooks”
In specific situations, we can monitor events outside of an application
An application can monitor BWS events across all applications
Can also inject events to another application
This can be a very useful technique
- examples?
This can be a security issue
- examples?
Take a look at jnativehook
- library to provide global keyboard and mouse listeners for Java.
- https://github.com/kwhat/jnativehook/
52
Bypassing Event Dispatch: Events for High Frequency Input
53
Pen and touch generate many high frequency events
- pen motion input can be 120Hz or higher
- pen sensor is much higher resolution than display
- multi-touch generates simultaneous events for multiple fingers
Problem: These events often too fast for application to handle
Solution: Not all events delivered individually:
- e.g. all penDown and penUp,
but may skip some penMove events
- Event object includes array of “skipped” penMove positions
- (Android does this for touch input)