Java Swings/Responsive Swing Application

In this section, we'll create an application that responds to a user action, namely the pressing of a button.

The Program
Last section, we wrote a program that displays a text label along with a button. In this section, we'll add functionality to the application so that the text changes when the user presses the button. In order to accomplish this, we'll write a subclass of  that can change its text, and implements the   interface. Because a JButton generates action events when pushed, we can connect our specialized JLabel to the JButton by registering it as a listener. Here's the code:

In this application, class  defines a special type of label that is an action listener (ie, that can receive ActionEvents) by implementing the   interface. It also has the ability to change its text through the private method. The  method just calls   when it receives an ActionEvent.

The main program code in  is similar to the code in the last section, but uses a   instead of an ordinary   object. It also registers the ChangeLabel as an  of the button with the button's   method. We can do this because JButtons create ActionEvents, and ChangeLabel is an ActionListener (ie, implements the  interface).

There's one thing to notice in the above example. Two classes are defined, one to contain the program code in the static main method, and another that defines a type used in the program. However, there's no reason that we can't put the  method directly in our new type's class. In fact, putting the program's  method in a customized subclass of a component is a common idiom in programming Swing applications. When reorganized this way, the program looks like this:

This program does exactly the same thing as the first, but organizes all the code into one class.

Multi-threading in Swing
The thread that performs actions inside the action, change, mouse and other listeners is called a Swing thread. These methods must execute and return quickly, as the Swing thread that must be available for the Swing framework to keep the application responsive. In other words, if you perform some time-consuming calculation or other activities, you must do this in a separate thread, not in the Swing thread. However then you access Swing components from the non-swing thread you initiated yourself, they may hang due race conditions if manipulated by the Swing thread at the same time. Because of that, Swing component from the non-Swing thread must be accessed through intermediate Runnable, using the  method:

This call will fire setText(message) in the appropriate time, when the Swing thread will be ready to respond. This approach is also usual when implementing the moving progress bar that only works properly if the slow process itself is implemented outside the Swing thread.