Concepts / Event Handling in Graphical User Interfaces

Event Handling in Graphical User Interfaces

A state machine is something that has a state and can change state in response to events or inputs, and its response to an event depends on the state it is in when the event occurs.

  • Programming

The Same Press, Two Different Results

Imagine a button in a program that you press repeatedly. Sometimes pressing it opens a menu, and at other times the same press closes it. Nothing about the press itself has changed. What has changed is the program's memory of what it is currently doing.

Keep one question in mind as you read: if an event arrives, what information must the program consult before it decides how to respond? By the end of this article you should be able to answer that question for a small program and trace how one event produces different outcomes in different situations.

Tracing a Wall Light Through Its States

Consider a simple wall light controlled by a single button. The light has two states, on and off, and it has one kind of event: a button press. The state can be stored in a single boolean variable named lightIsOn. The response to a press depends on that state, so the same event leads to two different results.

Light offlightIsOn is falseLight onlightIsOn is truebutton pressbutton press
Each box is a state, and each arrow is a response to an event. Both arrows carry the same label, so the event is identical. Only the starting state differs, and that difference alone determines where the light ends up.

What do you think happens?

The light is off. What happens when the button is pressed?

  • The light turns on

  • The light turns off

  • Nothing happens

Reveal answer
Answer:

The light turns on

The press is an event, and the machine responds to it based on its current state. Because the state is off, the machine follows the arrow that leads to the on state.

Now take the same button press while the light is on. The event is identical, but the state is not, so the machine follows the other arrow and turns the light off. Nothing in the button itself distinguishes the two cases. The state variable is what makes the difference.

What a State Machine Is

Definition

A state machine is something that has a state and can change state in response to events or inputs. Its response to an event depends on the state it is in when the event occurs.

Computer scientists use the name state machine for anything that remembers a condition of its own and changes that condition when something happens to it. The wall light fits this definition: it remembers whether it is on or off, and a button press changes that memory.

In an object-oriented program, the information stored in an object's instance variables is called the state of that object. The state is the collection of values that describe the object at a given moment, and those values determine how the object looks or behaves.

This produces two consequences. First, when one of the object's methods is called, the action the object takes can depend on its state, because the method can read the instance variables and decide what to do based on what it finds there. Second, the state can change, because the method can assign new values to the instance variables, so the next call may behave differently from the last one.

The state machine viewpoint is a planning tool as well as a description. If you can name an object's states and the events that move it between them, you have a clear plan for the methods that the class needs. Each event becomes a method, and each method's behavior is written as a function of the current state.

Event-Oriented Programs and Their State

The state machine viewpoint is especially useful in event-oriented programming, the style required by graphical user interfaces. In such a program, nothing runs from top to bottom in one fixed sequence. Instead, the program waits for events, such as key presses or mouse actions, and each event triggers a handler that runs in response.

Because a handler can run at any moment, the program must always know its own condition when an event arrives. The source suggests asking a set of design questions when building a GUI program: what information about state must be tracked, which events can change that state, how the response to a given event depends on the current state, whether the appearance of the interface should change to reflect a state change, and how the drawing code should take the state into account.

Reading the State Variables in KeyboardAndFocusDemo

The source uses a program called KeyboardAndFocusDemo to show these ideas. The state of that program is recorded in three instance variables named squareColor, squareLeft, and squareTop. Variables of this kind, which store the state of an object or program, are called state variables.

State variables do two jobs. The paintComponent() method reads them to decide how to draw the panel, so the appearance of the program follows its state. The two key-event-handling methods assign new values to them, so the state changes as the user types. Reading and writing the same variables is what connects the events to the display.

KeyboardAndFocusDemosquareColorstate variableKey-event handlersassign new valuessquareLeftstate variablepaintComponent()reads values to drawsquareTopstate variableholdsholdsholdsassignsassignsassignsreadsreadsreads
The three state variables sit at the center. The key-event handlers write to them, and paintComponent() reads them to draw the panel. Reading and writing the same variables links each event to what the user sees.

Finding Hidden State in a Game-Like Program

State is not always obvious. In a different game-like program, the source asks what counts as state at all. The positions of the boat, submarine, and bomb are state, and so is the fact that the bomb is sometimes falling and sometimes not. That falling-or-not difference is represented by a boolean variable, bomb.isFalling. Similarly, whether the submarine is moving left or right is a boolean, sub.isMovingLeft, and whether the submarine is exploding is another boolean, sub.isExploding.

An explosion lasts over several frames, so a single true or false value is not enough. The author uses an integer, sub.explosionFrameNumber, to count how many frames have been drawn since the explosion began. The value of that integer matters only while an explosion is in progress. A state can therefore need more than one variable, and some variables are meaningful only under particular conditions.

Same Event, Different Results in Code

The following class implements the wall light from earlier. The button press is a method, and the method's behavior depends on the instance variable lightIsOn. The code is an illustrative example written for this article, not taken from the source.

java
Output
After the first buttonPressed() call, isOn() returns true. After the second call, isOn() returns false.
Notes on the code
  • lightIsOn is the state variable that records the light's condition
  • buttonPressed() is the event handler, and it reads the state before deciding what to do
  • The assignments inside the if and else branches change the state for the next call

Trace the two calls. Both calls run the same method with the same event, but the first call finds lightIsOn as false and takes the else branch. The second call finds it as true and takes the if branch. The method body is the same both times; the only thing that differs is the value stored in the state variable.

Button presslightIsOn is falseLight turns onlightIsOn becomes trueButton presslightIsOn is trueLight turns offlightIsOn becomes falsehandler runshandler runs
The same event, a button press, arrives in two different states. Placing the two cases side by side shows that the event is identical and the outcome depends on the stored state.

Mistakes Beginners Make With State

  • Common mistake

    Assuming the event alone determines the response

    What it looks like

    Believing that a button press always opens the menu because the press looks the same every time.

    Why it fails

    The source's central point is that the response to an event depends on the state the machine is in when the event occurs. The press is identical in both cases; the stored condition is what differs.

    Do this instead

    Before deciding what an event does, identify the state variables the handler will read.

  • Common mistake

    Forcing every state into a single boolean

    What it looks like

    Using only a true or false value to represent an explosion that lasts several frames.

    Why it fails

    The source shows that an explosion needs a counter, sub.explosionFrameNumber, because a single true or false value cannot record how many frames have passed.

    Do this instead

    Ask whether the state needs more than one variable, and recognize that some variables matter only under particular conditions.

  • Common mistake

    Planning an event-oriented program as one top-to-bottom sequence

    Why it fails

    Event-oriented programs wait for events and run handlers at arbitrary moments. The source says top-down, step-wise refinement does not apply to their overall design.

    Do this instead

    Plan a collection of states, the events that can occur, and the response for each combination.

Practice: Tracing a Light Through Presses

EASY

Using the WallLight class from earlier, start with the light off. Trace the state of lightIsOn and the output of isOn() after each of these calls in order: buttonPressed(), buttonPressed(), buttonPressed(). Then explain why the third press gives a different result from the first, even though the event is identical.

Hints
  • Write down the value of lightIsOn before each call, then apply the if or else branch.
  • The first press starts from the off state. The third press starts from whichever state the second press left behind.

Key Takeaways

  • A state machine has a state and changes that state in response to events or inputs, and its response to an event depends on the state it is in when the event occurs.
  • In an object, the state is held in instance variables, which methods read to decide what to do and assign to change what happens next.
  • Event-oriented programs such as GUIs wait for events and run handlers at arbitrary moments, so they are organized around identifying state variables, the events that change them, and how responses depend on the current state.
  • The same event can produce different results in different states, as the wall light shows: an identical button press turns the light on or off depending on lightIsOn.
  • Some states need more than one variable, such as a boolean plus a frame counter, and state can be less obvious than it first appears.