Nov 29
Mouse events from Java Swing report the
click count. When mouse events are generated within some click threshold (which should be an operating system setting), the click count increases. One common problem is processing single- versus double-clicks. Java does not hold back the single-click event (
click count of 1) even when a double-click (
click count of 2) may be forthcoming. This is for good reason: As well designed of a programming language that it is, Java cannot see the future.
There are techniques (documented elsewhere) for dealing with this aspect of mouse processing in Java. The impetus for this article is mouse event inconsistencies between platforms. Particularly, click counts seem to be reported differently for different events on different platforms.
Read the rest of this entry »
Sep 20
JTextArea is a convenient Swing component to use when word-wrapping is needed. To display a list of multi-line messages, for example, the obvious solution is to use a JTextArea as the ListCellRenderer Component for a JList (within a JScrollPane). However, you will soon find that the text often does not end up word-wrapped as expected.
After reading post after post of mystic incantations, none of which actually seem to fully work, I present
my solution for using a JTextArea in a JList: Don't.
Read the rest of this entry »
Jul 25
It's old news that Java's Swing GUI toolkit follows a deficient Model-View-Controller (MVC) architecture. In most cases, Swing fuses together the notion of the View and Controller, but offers a separate Model. At least, that's what the naming convention implies. For example, JComboBox should be a View-Controller to a ComboBoxModel.
This particular case failed me today.
Read the rest of this entry »
Feb 09
The cleanest way to close a Java GUI application is to dispose of all top-level resources (JFrame instances, for example) and allow the AWT/Swing thread to close itself. Calling
System.exit(0) or
Runtime.getRuntime().halt(0) is often prescribed, but not recommended, as it could preempt proper shutdown procedures in your application.
If your Java GUI application uses DISPOSE_ON_CLOSE mode, check that your process is exiting cleanly. If it is not, the most likely culprit is that the AWT Event Dispatch Thread is still active. This is well-known AWT/Swing behavior, but there is a scenario in which Java will refuse to shut down this thread, even with all resources closed and disposed.
Read the rest of this entry »
Jul 18
This article covers a handy bit of logic to
stabilize Java/Swing components that otherwise have annoying grow/shrink behavior. The (perceived) problem occurs when a Java/Swing application uses layout managers that obey internal components' desired sizes. The layout shifts to accommodate internal components as they grow/shrink, which can cause much distress to the end user (at least it does to me).
Read the rest of this entry »
Jun 18
This article presents a simple programming technique for ensuring Java Swing tasks are executed on the proper thread, while avoiding unnecessary delayed invocation.
Read the rest of this entry »
Aug 24
Elderly swing-set factory employees using thread instead of chains forces product recall?
No. Why would you think that?
This article describes how the javax.swing.Timer utility can cause your Swing application to hang at shutdown, and how to fix it.
The Timer utility is useful for repeating tasks on the Swing/AWT thread. They're handy enough to create in many places throughout GUI code. However, each one that remains active keeps the AWT thread alive, which prevents clean application shutdown (without resorting to System.exit()). Lacing the code with Timer instances makes it difficult to track them all down and stop them when the application is supposed to exit.
To correct the situation for the MMORPG client, I created a simple factory class with a create(..) method for producing Timer instances. The factory maintains a reference to every Timer created. At application shutdown, the factory's stop() method is called, which tells each Timer to stop(). After replacing all Timer constructor calls with the factory's create(..) method, the MMORPG client exits cleanly.
There are a few caveats. For one, you must be certain it is safe to stop Timers in this way (a Timer may be carrying out some critical pre-shutdown operation). In general, I only use Timers for GUI-related activities, and not to drive application logic. Another weakness is that the factory cannot guarantee the Timers will not be restarted, or that more timers will not be created, after stopping the factory. This could be guarded with a more sophisticated design, such as a TimerProxy class to prevent post-shutdown starting, refusing to create new timers after shutdown, or an isStopped() method for GUI code to query.
For the MMORPG client, this simple factory pattern is sufficient to untie Timers from the AWT thread, allowing clean shutdown without resorting to System.exit().