Chapter 4 JFC Programming Techniques
- In This Chapter
- Thread Safety Requirements of JFC
- The Repaint Manager
- Actions
Writing applications and applets using the JFC toolkit isnt that different than using any other toolkit written in Java. However, there are some issues that must be understood when designing a JFC-based application. The first is that the Swing component toolkit is not thread safe. Code that alters the state of Swing components must be executed in the event-dispatch thread. Therefore, if your application contains multiple threads that need to report information to the user, special programming techniques must be used.
The Swing toolkit optimizes painting through the use of a repaint manager. Understanding this class, and creating your own repaint manager if necessary, can enhance the performance and visual appearance of Swing applications.
The Action interface is provided in the Swing toolkit to allow a single bit of functionality to be easily added to multiple user interface controls. The Action interface is an extension of the ActionListener interface contained in the AWT. As such, an Action can be used anywhere an ActionListener can be used. However, as we will see later in this book, Actions are integrated with menus and toolbars in the JFC.
This chapter discusses some of the unique programming techniques required to design and write complete JFC applications and applets. You will learn
- How to write thread-safe JFC code
- How to use the RepaintManager
- How to encapsulate bits of application functionality in an Action
Thread Safety Requirements of JFC
JFC requires that Swing components be accessed by only one thread at a time. The normal thread of execution is the applications event-dispatch thread. JavaSoft documentation states the following:
- Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatch thread.
While this requirement may seem onerous at first glance, you wont often need to access components from other threads, and when you do, the SwingUtilities class provides an easy mechanism to execute code on the event-dispatch thread.
Components are considered to be realized as soon as their setVisible, show, or pack methods are called. Components are also considered realized when they are added to a container that is realized.
The event-dispatch thread is the applications main thread of execution. All event listeners are called on this thread, so you normally dont need to be concerned about thread safety. If you are creating threads, however, you must ensure that their execution is thread safe when accessing Swing components.
Exceptions to the Rule
There are a few exceptions to the requirement of not accessing Swing components on threads other than the event-dispatch thread. The repaint, revalidate, and invalidate methods are thread safe and can be called by any thread, including timer threads. These methods use different techniques to obtain thread safety. The repaint and revalidate methods use the repaint manager to post a message to the event-dispatch thread to call paint and validate, respectively. If multiple repaint or revalidate messages are in the queue when they are to be dispatched, the repaint manager will attempt to collapse the multiple events into a single event call. The invalidate method uses the more traditional approach to thread safety: It obtains a lock on the component and marks it as invalid. In addition to these methods, all of the methods to add and remove event listeners are guaranteed to be thread safe.
main Entry Point Considerations
The code in an applications main entry point is not executed in the event-dispatch thread. To be absolutely safe, you should not place any GUI code after the first call to either the setVisible, show, or pack method. JavaSoft documentation says the following code is typically safe, even though the show method follows the pack method.
public class MyApplication {
public static void main(String[] args) {
JFrame frame = new JFrame(MyApplication);
// add JFC components here
frame.pack(); // realizes components
frame.show();
// No more GUI calls!
}
}
This is because its unlikely that a paint call will reach the frame before the show method call returns. After the show call, the GUI event dispatching moves from the main thread to the event-dispatching thread. All subsequent calls that alter JFC components must be in the event-dispatch thread.
|