Home > Articles > Programming > User Interface (UI)

The Cross-Platform Java GUI: Designing Code for More Than One Operating System

Marcus Zarra
  • PrintPrint
  • Share ThisShare This
  • DiscussDiscuss
Close WindowMarcus Zarra

Marcus Zarra

Learn more…

Marcus Zarra and Matt Long on Core Animation
Jun 5, 2009
Introduction to Migration in Apple's Core Data
Mar 7, 2008
A Look at Apple's Core Animation
Feb 1, 2008
The State of Java Development on OS X
Jan 4, 2008
Packaging Your Application for OS X
Nov 21, 2007
Tiger vs. Leopard: Which Should You Develop For?
Oct 26, 2007
Building on Apple Sync Services
Sep 8, 2006
Getting in Sync with OS X
Sep 1, 2006
Syncing Your Data the Cocoa Way
Aug 11, 2006
Controlling Both Ends of the Communications Channel: From Cocoa to Servlets
Jun 2, 2006
Cocoa: Working with XML
May 19, 2006
Java EJB 3.0: A Hibernate Clone?
Apr 28, 2006
Document Level Parameters Using Core Data: A Guide for Cocoa Developers
Apr 7, 2006
Tips for J2EE Development
Feb 24, 2006
The Cross-Platform Java GUI: Designing Code for More Than One Operating System
Feb 10, 2006
Avoiding Java Exception Abuse
Dec 22, 2005
Java Perspective: Advanced Core Data
Dec 16, 2005
Java Perspective: Cocoa-Java Bridge
Dec 1, 2005
Java Perspective: Core Data and the Mac OS X Developer
Nov 23, 2005
Java Perspective: Key-Value Protocols, Behind the Magic of Mac OS X Development
Nov 11, 2005
Java Perspective: Cocoa Subclasses and Delegates
Nov 4, 2005
The Java Perspective: Cocoa's Interface Builder
Oct 21, 2005
Maven: Handling Multiprojects
Sep 23, 2005
Java, Maven, and Your Web Development Project
Aug 26, 2005
Ant User, Let Me Introduce Maven
Jul 29, 2005
Using JAAS Authentication with JBoss
Jun 17, 2005
Building a Custom JBoss Login Module
Jun 10, 2005
Testing Java Enterprise Applications with Cactus
May 20, 2005
Ant: Building a Better Build File
May 6, 2005
XDoclet: Entity Bean Relationships
Apr 8, 2005
The Java Developers' Introduction to XDoclet
Jan 7, 2005
An Introduction to Cactus
Dec 30, 2004
Using Multiple Databases with JBoss
Nov 24, 2004
JBoss Application Configuration Breakdown
Nov 5, 2004
Sortable Swing JTable
Oct 1, 2004
Building a Professional Swing JTable
Sep 10, 2004
Creating a Custom Java Swing Tablemodel
Aug 27, 2004
Adding Workflow Control to Your Java Applications
Mar 26, 2004

Sorry, this author hasn't posted any blogs.

Cross-Platform GUI Programming with wxWidgets

Like this article? We recommend
Cross-Platform GUI Programming with wxWidgets

As cross-platform languages go, Java is considered one of the best choices available. It has a rich library for GUI development that is available on every platform on which Java is available. However, there is more to building a cross-platform GUI than just writing the code. Marcus Zarra steps you through a few things that need to be considered when designing an application with the intent of using it on multiple platforms.

One of the most accurate complaints users have against Java GUIs is that they do not feel native. While this is partially due to the way that Swing is designed, it is also partially the fault of the developer. It is quite common for a developer to design the GUI to work on his or her platform of choice and then rely solely on Java’s cross-platform nature to make the application available for other operating systems. This behavior naturally leads to users on the other platforms complaining about the lack of a native feel for the application.

Installation

First impressions are vital, and the installation procedure for your application is your only first impression. If the user has to go through an arcane ritual to get your software installed, it already has that "non-native" feel to it. But what is considered an acceptable installation procedure? Unfortunately, that procedure varies completely on each system. Here are a few examples.

Windows

Windows users expect an installer. Simple as that. They expect an application that puts all the little bits in the right places when they run it and places an icon where they want it. They expect the installer to ask them where they want the icons and to only put them there. They also expect this installer to put the right information into the registry so that if they want to uninstall the application it will properly remove all its bits and pieces.

Fortunately, there are several very good Windows installers available on the market today. Some of them are even free or available at a small cost. If Windows is a primary target for your application, it is worth it to not only invest in a good installer but also to make sure you understand it fully so that there are no mishaps. A failed uninstall on Windows is almost as bad as a failed install. An improper uninstall tends to leave a bad aftertaste and might keep the user from selecting any other software from the same developer.

OS X

Arguably OS X has the easiest install available. Users expect to just drag the application to wherever they want it on their computer and just double-click the icon. Anything more than that feels wrong and overly complicated to the user. OS X expects an application to be completely self-contained inside an application directory structure. From the user’s point of view, the application will be just a single icon because OS X automatically treats the folder structure as if it were a single file when it has an .app extension. Unfortunately, there is more to creating a properly built OS X application than just putting everything in the right directory. Assuming that you have access to an OS X machine on which to build your application, there is a simple ant build script that will produce the proper structure for the application bundle:

 <target name="dist.mac" depends="all">
  <mkdir dir="${dist}/${app}"/>
  <property name="appdir" value="${dist}/${app}/${app}.app"/>
  <mkdir dir="${appdir}/Contents/Resources/Java"/>
  <mkdir dir="${appdir}/Contents/Resources/logs"/>
  <copy file="${packaging}/JavaApplicationStub" 
   todir="${appdir}/Contents/MacOS"/>
  <exec command="chmod 755 ${appdir}/Contents/MacOS/JavaApplicationStub"/>
  <copy file="config/log4j.properties" todir="${appdir}/Contents/Resources"/>
  <copy file="config/Info.plist" todir="${appdir}/Contents"/>
  <copy file="images/${app}.icns" todir="${appdir}/Contents/Resources"/>
  <copy todir="${appdir}/Contents/Resources/images">
   <fileset dir="images" includes="*png"/>
  </copy>
  <copy file="dist/${app}.jar" todir="${appdir}/Contents/Resources/Java"/>
  <copy todir="${appdir}/Contents/Resources/Java">
   <fileset dir="lib"/>
  </copy>
  <exec dir="${dist}" executable="hdiutil">
   <arg line="create -ov -srcfolder ${app} ${app}.dmg"/>
  </exec>
  <delete dir="${dist}/${app}"/>
 </target>

This fairly straightforward ant task not only builds the entire file structure needed for the application to be properly executed on OS X but also stores the created application in a disk archive. While this task makes fairly heavy use of variable substitution, the names of the variables should make it clear exactly what it is copying and to where.

This must be executed on an OS X machine because of the launcher that is copied into the file structure. Without that, it would be possible to create this entire thing on any machine. In fact, if you had a copy of the JavaApplicationStub on another machine, it would be possible to build it without access to an OS X machine. You would simply need to remove the hdiutil step and zip or tar up the finished app instead.

Included in this ant build file is the Info.plist file, which is the file that OS X turns to when it needs information about the application. A sample of this file is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
 "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
 <dict>
  <key>CFBundleName</key>
  <string>MyApp</string>
  <key>CFBundleVersion</key>
  <string>10.2</string>
  <key>CFBundleAllowMixedLocalizations</key>
  <string>true</string>
  <key>CFBundleExecutable</key>
  <string>JavaApplicationStub</string>
  <key>CFBundleDevelopmentRegion</key>
  <string>English</string>
  <key>CFBundlePackageType</key>
  <string>APPL</string>
  <key>CFBundleSignature</key>
  <string>????</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleIconFile</key>
  <string>MyApp.icns</string>
  <key>Java</key>
  <dict>
   <key>WorkingDirectory</key>
   <string>$APP_PACKAGE/Contents/Resources</string>
   <key>MainClass</key>
   <string>com.zarrastudios.Main</string>
   <key>JVMVersion</key>
   <string>1.3+</string>
   <key>ClassPath</key>
   <array>
    <string>$JAVAROOT/myapp.jar</string>
    <string>$JAVAROOT/commons-logging.jar</string>
   </array>
   <key>Properties</key>
   <dict>
    <key>apple.laf.useScreenMenuBar</key>
    <string>true</string>
    <key>com.apple.hwaccel</key>
    <string>true</string>
   </dict>
  </dict>
 </dict>
</plist>

This simple xml file gives OS X all the information it needs about the application, its icon, its properties, and the location of all files to properly build the classpath prior to execution.

Solaris

Sun has its own packaging system and recommends that deployments for Solaris use their packages instead of just a tar file. Fortunately, its system, although arcane, is simple to build against once you are familiar with it. I have yet to produce an ant build script for Sun and I generally run the steps from the command line. First, it requires two files that will describe the package.

The first file is called pkginfo and it looks like this:

PKG="MyAppPackage"
NAME="MyApp"
ARCH="sparc"
VERSION="1.00"
CATEGORY="application"
VENDOR="zarrastudios.com"
EMAIL="nobody@nowhere.com"
PSTAMP="Marcus S. Zarra"
BASEDIR="/usr/local"
CLASSES="none"

The second file is called prototype:

i pkginfo=./pkginfo-client
d none /usr 0755 root other
d none /usr/local 0755 root other
d none /usr/local/MyApp 0755 root other
d none /usr/local/MyApp/conf 0755 root other
d none /usr/local/MyApp/lib 0755 root other
f none /usr/local/MyApp/lib/example.jar 0644 root other
f none /usr/local/MyApp/conf/log4j.xml 0644 root other

With these two files in hand, it is now just a matter of executing two command-line programs to build the package:

pkgmk -r ´pwd´ -o MyApp

This produces the actual package. Once it is created, the next step is to make it transportable:

cd /var/spool/pkg
pkgtrans -s ´pwd´ /tmp/MyApp
  <<Select MyApp from the menu>>
cd /tmp
gzip MyApp

Now the completed application is sitting inside a gzipped Sun package and is ready for deployment.

  • Share ThisShare This
  • Your Account

Discussions

Make a New Comment

You must log in in order to post a comment.

Related Resources

Danny KalevMinutes from the October 2009 Meeting
By Danny Kalev on November 19, 2009 No Comments

The minutes from the Santa Cruz (October 2009) meeting are available here. Even if you're not a language layer at heart, I encourage you to read them.

Danny KalevA Reader's Opinion on Attributes
By Danny Kalev on October 20, 2009 No Comments

In August I dedicated a series to the debate about C++0x attributes. I believe that it covered the subject in a balanced and detailed way, but I keep getting complaints from C++ users who don't like attributes for various reasons. Here's a recent email I received from a Polish C++ programmer. While it  doesn't represent my opinion about attributes -- I'm rather neutral about this feature and consider it a "solution waiting for a problem" -- but it suggests that attributes are still a highly controversial issue that will haunt C++ for a long time. The email is quoted here with minor edits that and as usual, with all private details removed.

Danny KalevFollowup: The Web 2.0 Guy I Ain't
By Danny Kalev on October 16, 2009 1 Comment

Almost a year ago, I posted here The Web 2.0 Guy I Ain't. People wonder whether I still resist all those Web 2.0 features and technologies at the end of 2009.

See All Related Blogs

Informit Network