Long before the web became the dominant application platform, Java’s “Write Once, Run Anywhere” promise was most visibly realized in its graphical user interface (GUI) toolkits. The ability to create a desktop application that ran identically on Windows, Mac, and Linux was a killer feature. This is the story of that journey, from a clunky beginning to a powerful but ultimately superseded revolution.

Act I: AWT - The First Attempt

Java 1.0 shipped with the Abstract Window Toolkit (AWT). Its approach was simple and logical: provide a set of common UI components (buttons, text fields, labels) and map them to the underlying operating system’s native UI components, or “peers”.

  • The Good: An AWT application on Windows looked like a real Windows application. On a Mac, it looked like a real Mac application. It was truly native.
  • The Bad: This created the “least common denominator” problem. If a component didn’t exist on all platforms (like a table or a tree), it couldn’t be included in AWT. This led to a very limited set of widgets. Worse, subtle differences in how each OS handled its peers led to a constant stream of platform-specific bugs, earning AWT the nickname “the Awkward Window Toolkit.”

Act II: Swing - The Pure Java Revolution

To solve AWT’s problems, Sun Microsystems introduced the Java Foundation Classes (JFC) with Java 1.2, the centerpiece of which was a new GUI toolkit called Swing. Swing took a radically different approach.

Instead of using native OS peers, Swing components were “lightweight” and painted entirely by Java itself, pixel by pixel. This had two revolutionary consequences:

  1. Consistency: A Swing application looked and behaved exactly the same on every single platform, eliminating the AWT bug-hunt.
  2. Pluggable Look and Feel (PLAF): Since Java was doing all the drawing, it could be told how to draw the components. Developers could make their application look like Windows, Mac, or a new, platform-independent theme called “Metal” with a single line of code.

Swing provided a rich set of components that AWT lacked, like JTable, JTree, and JTabbedPane, and it powered the golden age of Java desktop development, including iconic applications like the NetBeans and early IntelliJ IDEA IDEs.

To see what a classic Swing application felt like, here is a simple interactive emulation of the “Metal” look and feel:

My Swing App

Hello, World!

Act III: The World Changes, and So Does Java

Swing was powerful, but two major shifts in the industry changed its trajectory:

  1. The Rise of the Web: Rich web applications built with AJAX, and later modern JavaScript frameworks, began to replace traditional desktop applications for many use cases.
  2. The Mobile Revolution: The dominance of iOS and Android created new platforms where Swing did not run.

In response, Oracle introduced JavaFX as the official, modern successor to Swing. It was designed from the ground up with features like CSS for styling, FXML for declarative UI design, and better support for modern graphics and media.

After Java 8, JavaFX was unbundled from the JDK to allow it to evolve at its own pace. It now thrives as the independent OpenJFX project and is actively developed by a dedicated community.

How Do You Build a GUI in Java 21?

So, if you want to write a desktop application in Java today, what are your options?

  1. JavaFX (via OpenJFX): This is the recommended modern path for new, sophisticated desktop applications in Java. It’s powerful, themeable, and fully supported.
  2. Swing: Swing is not dead! It is still included with the standard JDK and is perfectly stable and capable. For internal business tools, utilities, or maintaining legacy applications, it remains an excellent and simple choice.
  3. Third-Party and Multi-Platform Toolkits: The JVM ecosystem is vibrant. Jetpack Compose for Desktop (from JetBrains and Google) allows you to use the modern, declarative UI model of Android to build desktop apps in Kotlin and Java. Frameworks like Vaadin allow you to write a web UI entirely in Java.
  4. Web UIs with a Java Backend: Many modern “desktop” applications are now a web-based UI (built with tools like Electron or just a web browser) that communicates with a powerful, robust backend server written in Java.

The story of Java’s GUI is one of constant adaptation. From the native bindings of AWT to the self-drawn revolution of Swing and the modern approach of JavaFX, it reflects the changing face of how we interact with software.