Core Java

Swing on Steroids: Modernizing Java Desktop Apps with FlatLaf and JReleaser

Java Swing has been around for decades, but that doesn’t mean your desktop apps need to look dated. With the right tools, you can create modern, stylish applications that support dark mode, high-DPI displays, and native installation packages. Let’s explore how to supercharge Swing development using FlatLaf for UI styling and JReleaser for distribution.

1. Creating Modern UIs with FlatLaf

FlatLaf is a open-source Look and Feel for Java Swing that brings your applications into the 21st century with:

  • Flat design aesthetics – Clean, modern interfaces without the old-school 3D bevels
  • Dark mode support – Automatic theme switching based on system preferences
  • High-DPI scaling – Crisp rendering on 4K displays and retina screens
  • Custom themes – Easy theming with JSON configuration files

Basic FlatLaf Setup

Getting started is simple. First, add the dependency to your project (Maven example):

<dependency>
    <groupId>com.formdev</groupId>
    <artifactId>flatlaf</artifactId>
    <version>3.4.1</version>
</dependency>

Then set the Look and Feel at startup:

import com.formdev.flatlaf.FlatLightLaf;

public class MyApp {
    public static void main(String[] args) {
        FlatLightLaf.setup();  // Light theme
        // OR for dark mode:
        // FlatDarkLaf.setup();
        
        // Your app code here
    }
}

Automatic Dark/Light Mode Switching

Modern operating systems let users choose between light and dark modes. FlatLaf can respect this preference:

// Enable automatic dark/light theme switching
FlatLaf.registerCustomDefaultsSource("com.myapp.themes");
UIManager.put("defaultFont", new Font("Segoe UI", Font.PLAIN, 13));
FlatSystemProperties.setProperty("flatlaf.useWindowDecorations", "true");

// Track system dark mode changes
FlatLaf.setup(new FlatMacDarkLaf());
SystemThemeDetector.init("com.myapp.MyApp");

High-DPI Support

For crisp rendering on high-resolution displays:

// Enable automatic scaling based on system DPI settings
System.setProperty("sun.java2d.uiScale.enabled", "true");
System.setProperty("sun.java2d.uiScale", "1x");
System.setProperty("flatlaf.uiScale", "1x");

// Or force a specific scaling factor
// System.setProperty("flatlaf.uiScale", "1.5x");

Custom Themes

Create a JSON file in your resources (e.g., themes/mytheme.json):

{
    "@base": "dark",
    "background": "#282a36",
    "foreground": "#f8f8f2",
    "accent": "#bd93f9",
    "selection.background": "#44475a"
}

Then load it:

FlatLaf.registerCustomDefaultsSource("themes");
FlatDarkLaf.setup();

2. Packaging as Native Installers with JReleaser

JReleaser is a tool that packages your Java application as native installers for various platforms:

  • Windows: MSI installers
  • macOS: Homebrew taps or DMG files
  • Linux: DEB/RPM packages
  • Cross-platform: ZIP archives with native launchers

Basic JReleaser Configuration

Create a jreleaser.yml file in your project:

project:
  name: myapp
  version: 1.0.0
  description: A modern Swing application
  authors:
    - Your Name <you@example.com>
  
distributions:
  app:
    artifacts:
      - path: target/myapp-${project.version}.jar
    java:
      mainClass: com.myapp.Main
    jlink:
      enabled: true
    nativeImage:
      enabled: false

release:
  github:
    owner: yourusername
    name: myapp

Platform-Specific Packaging

Windows MSI Installer:

assemblers:
  jpackage:
    - name: windows
      jpackage:
        imageName: MyApp
        imageOptions: ["--win-menu", "--win-shortcut"]
      formats: ["msi"]
      platform: windows

macOS Homebrew Tap:

brew:
  tap:
    owner: yourusername
    name: homebrew-tap
  formulae:
    - name: myapp
      install: |
        bin.install "myapp"

Linux DEB Package:

assemblers:
  jpackage:
    - name: linux
      jpackage:
        imageName: myapp
      formats: ["deb"]
      platform: linux

Building and Releasing

Run JReleaser with:

# Dry run (test configuration)
jreleaser assemble --dry-run

# Full release
jreleaser release

3. Putting It All Together: A Complete Example

Let’s create a simple dark-mode Swing app with native packaging.

1. Application Code (Main.java):

import com.formdev.flatlaf.FlatDarkLaf;
import javax.swing.*;

public class Main {
    public static void main(String[] args) {
        FlatDarkLaf.setup();
        
        JFrame frame = new JFrame("Modern Swing App");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        
        JButton button = new JButton("Click Me");
        JLabel label = new JLabel("Hello, Modern Java!");
        
        JPanel panel = new JPanel();
        panel.add(label);
        panel.add(button);
        
        frame.add(panel);
        frame.setVisible(true);
    }
}

2. Maven pom.xml:

<project>
    <!-- ... other config ... -->
    <dependencies>
        <dependency>
            <groupId>com.formdev</groupId>
            <artifactId>flatlaf</artifactId>
            <version>3.4.1</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.5.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.jreleaser</groupId>
                <artifactId>jreleaser-maven-plugin</artifactId>
                <version>1.8.0</version>
            </plugin>
        </plugins>
    </build>
</project>

3. Build and Release:

# Build the JAR
mvn package

# Create native packages
mvn jreleaser:assemble
mvn jreleaser:release

4. Advanced Tips

  1. Custom Icons – Replace standard Swing icons with SVG-based ones for perfect scaling on any display. Libraries like SVG Salamander can help render them in Swing.
  2. Animation – Use TimingFramework or Trident to add smooth transitions (e.g., fade-ins, sliding panels) without blocking the Event Dispatch Thread (EDT).
  3. Native Integration – JNA (Java Native Access) allows calling OS-specific APIs (e.g., Windows taskbar progress, macOS dock badges).
  4. Auto-Updates – Update4j enables self-updating apps by checking for new versions and applying patches without user intervention.
  5. App Stores – JPackage’s --mac-app-store flag helps package apps for distribution on the Mac App Store with sandboxing compliance.

Advanced Tips Summary (Table Format)

TipKey Tools/LibrariesUse CaseExample Benefit
Custom IconsSVG Salamander, FlatLaf IconsHigh-DPI displays, modern UICrisp icons at any resolution
AnimationTimingFramework, TridentSmooth transitions, loading indicatorsBetter UX with fluid motions
Native IntegrationJNA, JNIOS-specific features (notifications, badges)Windows taskbar progress bars
Auto-UpdatesUpdate4j, JReleaserSeamless app updatesUsers always get the latest version
App StoresJPackage (--mac-app-store)Distributing via Mac App StoreMonetization & wider reach

When to Use Each

  • For UI polish → Custom Icons + Animation
  • For OS features → Native Integration (JNA)
  • For maintenance → Auto-Updates (Update4j)
  • For distribution → JPackage + JReleaser

5. Resources to Explore Further

With these tools, your Swing applications can look and feel like modern native apps while maintaining Java’s cross-platform advantages. The combination of FlatLaf for styling and JReleaser for distribution removes the traditional pain points of Java desktop development.

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button