Skip to content

Archive

Tag: SWT

Java Web Start is a technology that allows easy deployment of Java based software through a web browser. The advantages of this framework are numerous but one nice thing is that it allows you far more freedom then the completely sandboxed Java applet. In this post I will detail how I converted my Hash Verifier application to run right from the browser.

Java Network Launching Protocol (JNLP)

The javax.jnlp libraries provide the functionality needed to launch the application from within a web browser. This is done through the use of a specially crafted XML file called a jnlp file. This file specifies the application information including the location of the executable jar and any class libraries associated with it. The nice thing about this is that it allows you to specify different class files spending on the platform it is being run on. This is exactly what I needed in order to get the correct SWT libraries loaded on the target platform.

As an example of what a jnlp file looks like here is the file I created for my Hash Verifier application:

<?xml version=”1.0″ encoding=”utf-8″?>
<jnlp spec=”1.0+” codebase=”http://www.tylerburton.ca/webstart” href=”hv.jnlp”>
<information>
<title>Hash Verifier</title>
<vendor>tylerburton.ca</vendor>
<homepage href=”http://tylerburton.ca” />
<description>A graphical file digest generator</description>
<description>Hash Verifier</description>
</information>

<security>
<all-permissions />
</security>

<resources>
<j2se version=”1.5+” />
<jar href=”HashVerifier.jar” />
</resources>

<resources os=”Windows” arch=”x86″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-win32-windows-x86.jar” />
</resources>

<resources os=”Windows” arch=”x86_64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-win32-windows-x86_64.jar” />
</resources>

<resources os=”Windows” arch=”amd64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-win32-windows-x86_64.jar” />
</resources>

<resources os=”Linux” arch=”ppc”>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-ppc.jar” />
</resources>

<resources os=”Linux” arch=”ppc64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-ppc64.jar” />
</resources>

<resources os=”Linux” arch=”x86_64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86_64.jar” />
</resources>

<resources os=”Linux” arch=”amd64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86_64.jar” />
</resources>

<resources os=”Linux” arch=”x86″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86.jar” />
</resources>

<resources os=”Linux” arch=”i386″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86.jar” />
</resources>

<resources os=”Linux” arch=”i686″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-linux-x86.jar” />
</resources>

<resources os=”Mac” arch=”x86_64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86_64.jar” />
</resources>

<resources os=”Mac” arch=”amd64″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86_64.jar” />
</resources>

<resources os=”Mac” arch=”x86″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86.jar” />
</resources>

<resources os=”Mac” arch=”i386″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86.jar” />
</resources>

<resources os=”Mac” arch=”i686″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-cocoa-mac-x86.jar” />
</resources>

<resources os=”Mac”>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-carbon-mac.jar” />
</resources>

<resources os=”SunOS” arch=”sparc”>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-solaris-sparc.jar” />
</resources>

<resources os=”SunOS” arch=”x86″>
<jar href=”http://www.tylerburton.ca/swt/3.6.1/swt-gtk-solaris-x86.jar” />
</resources>

<application-desc main-class=”ca.tylerburton.hashverifier.HashVerifierMain” />

</jnlp>

As you can see I have outlined all of the platform configurations that I am going to be compatible with. Java Web Start takes care of the rest for me automatically.

Digital signatures

The final step is to digitally sign the executable jar. This is required because when deploying an application that is not sandboxed, or one that requires access to low-level functions and libraries (as is the case in SWT), the end user needs to know that the code they are receiving came directly from the source. The easiest way to do this is to follow the instructions here. Unfortunately unless you are willing to pay to have your certificate signed by a trusted certificate authority the end user will need to click OK through a big security warning before they can use your program. It’s a small issue to overcome but if Minecraft can do it without too much of a headache I’m sure you can too.

Easy deployment

It’s as simple as that. I didn’t have to re-write my code, heck I didn’t even have to adjust a single line and it all just works. To see the result on your platform click here.

Note: unfortunately there is an issue with the Mac version of Java Web Start & SWT that prevents it from working correctly. Until Apple fixes this, or OpenJDK takes over and does it, SWT applications cannot be started correctly on that platform through Web Start.

Back in this previous post I mentioned the possibility of putting up a sort of how-to guide on SWT programming. Well I’ve finally found some time to do so. I will try to make this as step-by-step as possible so that anyone reading this will completely understand what I’m doing.

What you’ll need

I’m making the following assumptions before starting:

  1. That you’ve already installed the Java Development Kit (not just the Java Runtime)
  2. That you’ve installed Eclipse. You can use an alternative but all of my examples will be based on Eclipse. I’m also going to assume that you are at least familiar enough with Eclipse to compile a Java program.
  3. That you have some understanding of Java or at least some programming experience.
  4. That you have the SWT library for your platform downloaded. You can find this on the download page here.
  5. That you’ve created a project in Eclipse (or your IDE) for this walk through.

Import SWT

The first thing you want to do is import the SWT libraries that you have downloaded as an Eclipse project. Start by creating a new project specifically for SWT. For instance I named mine org.eclipse.swt (following the Java standard namespace naming conventions). Next import the SWT files into that project. To do this simply click File > Import and then choose Archive File under the General folder.

Then browse to the zip file you downloaded and choose the project to import this to (again in my example this project is org.eclipse.swt). When all is said and done you should have a project in your workspace for SWT similar to the one I’ve got here:

SWTify your project

To finish adding the SWT libraries into your project we need to add them to your project’s class path. Right-click on your project and click properties. On the left hand side of the window you will see an item called Java Build Path. On that page there will be a number of tabs: Source, Projects, Libraries, etc. Click Projects and then click the Add button. Select the org.eclipse.swt project and click OK. You should see something like this indicating that the SWT libraries will be included in your project’s build path.

We are now ready to begin programming!

The default SWT program

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class MySWTProject {

     public static void main(String[] args) {

          Display display = new Display();
          Shell shell = new Shell(display);

          shell.open();

          while(!shell.isDisposed()) {
               if(!display.readAndDispatch()) {
                    display.sleep();
               }
          }

          display.dispose();
     }
}

OK so what does it mean. In SWT all of the graphical things that you can do are tied to a Display object. A Display is essentially a link to the OS’ underlying graphics output. What we are talking about is not a monitor – in fact a Display can contain multiple monitors – but rather a more abstracted concept of graphics. If this sounds confusing don’t worry, for the most part that’s all you’ll really need to know about the Display object.

A Shell should be a little easier to understand. It represents a window, the base application container. In fact if you run the above program you should see something like this:

A Shell can be manipulated in all of the ways that you think it would be. For instance you can give it a title by using the setText() method.

shell.setText(“Here is my window title”);

The open() method tells the Shell to start displaying itself. You can also do some interesting things like using the pack() method to size the Shell in order to make it just large enough to hold whatever you put into it.

The little while loop part first checks to make sure that our shell still exists and then executes any input that we may want our application to respond to (via the readAndDispatch() method). Finally we dispose of all resources we have requested from the OS by calling dispose() on the Display object. This is important because unlike regular Java programming we do not get automatic garbage collection in SWT. There is a silver lining however – calling dispose() on an object like Display will automatically call dispose() on any children that are registered with it. That is why we didn’t need to call dispose() on our Shell.

OK I get it, now show me a button

Interaction is very easy to add. For instance we can add a button to our Shell above by simply adding the following code after the line where we create our Shell.

     Button button = new Button(shell, SWT.PUSH);
     button.setText("Push Me");
     button.pack();

Of course you will also need to import the Button library for this to work. In the constructor we pass in the shell (where we want to attach this button, similar to how we attached our shell to the Display object) and a flag called SWT.PUSH. SWT.PUSH tells the button to act as a push button. Next using setText() again we set the button label. Finally using the pack() method, as described above, we can resize the button to be just large enough. If you re-run the program now you will should see something like the following:

Pretty simple stuff. We can even add an action listener that will respond when the button is pressed by using code like this:

button.addSelectionListener(new SelectionListener() {
    public void widgetDefaultSelected(SelectionEvent e) {
          widgetSelected(e);
     }

     public void widgetSelected(SelectionEvent e) {
          System.out.println("The button was pressed!");
     }
});

Again very simple. I hope that this very brief introduction will help people realize that SWT programming is very similar to regular AWT/Swing GUI creation (although each has their own unique weirdness). If you would like to download the sample code file that I used to create this you can do so here. Please let me know if you have any questions about what I have said above, I’d be happy to help. On the other hand if you want a more in-depth look feel, free to hop over to my Hash Verifier post and grab a copy of the source there. The Eclipse Foundation also has an excellent code snippet section here that will show you how to use each GUI widget.

Happy programming.

After reading up on how you can use SWT to give Java a more native look and feel I was interested in giving it a shot first hand. I decided to break out old faithful (Hash Verifier) and re-write it completely in Java/SWT. The end result was an application that has essentially equivalent functionality (see below for differences) but is completely cross-platform. No matter what operating system you end up running this on (Windows, Mac OSX, Linux) it should have a native look and feel. I will explain how I accomplished this literal “write once, run anywhere” code below.

Easy deployment

The download consists of three different programs. The first, and main, named HashVerifier.jar is not actually the Hash Verifier program, but rather a simple sequential application launching system that I wrote to make cross-platform deployment even easier. When you run HashVerifier.jar, either by double-clicking on it or by running it from the terminal with java -jar HashVerifier.jar, it opens up the included rules file and begins to execute the lines one after another. If there is a special platform specific file (such as rules.mac) it will run that instead. Let’s take a look at rules:

java -jar AdaptiveSWT swt.jar
java -XX:+AggressiveOpts -XX:+UseParallelGC -jar HashVerifierApp

As you can see each line is a separate command to be run.

Getting that right look

When HashVerifier.jar starts it reads each line and runs that as a shell command. The line java -jar AdaptiveSWT swt.jar starts the second included program. AdaptiveSWT uses Java’s built in cross-platform UI toolkit, Swing, and displays a small dialog while it downloads the platform’s native SWT library. This is necessary because otherwise I would need to create separate downloads for each platform, each with their unique native SWT library. By using AdaptiveSWT I can instead let it handle all of the dirty work for me. This is really the trick that lets me release exactly one version of the program that looks correct for everyone. The AdaptiveSWT program is even smart enough to know not to re-download the library if you already have it. That being said if you ever do have an issue where you need to re-download the library either delete the swt.jar file in the program directory or change the first line to java -jar AdaptiveSWT -force swt.jar. This forces the download to happen regardless of it you already have it or not.

Hash Verifier

The next line logically starts the actual Hash Verifier application (with a couple of extra performance enhancing flags passed along as well). This version should work almost identically as the previous with a few key differences:

  • I have removed the Export to Hash File menu option as I simply just didn’t use it enough to warrant me spending the time to re-develop it.
  • I have removed the old Help menu option and replaced it with a visit website option.
  • RIPEMD-160 has been replaced with MD2, mostly because that is what the JVM supports “out-of-the-box”.

That’s about it. Please let me know if you have any issues running it on your platform of choice.

Requirements

  • OS: Windows, Mac OSX or Linux (Gtk+)
  • Internet connection
  • Java JRE (targeted at JavaSE-1.6 but might work on the previous version as well)

As before the binary only package contains just the executables, whereas the all package contains the source code as well.

Binary Only Package All Package
File name: hash_verifier_0_3_0_0_binary.zip hash_verifier_0_3_0_0_all.zip
File hashes: Download Here
GPG signature: Download Here Download Here
Screenshots:
License: (LGPL) View Here
Version: 0.3.0.0
File size: 68.6KB 107.1KB
File download: Download Here Download Here

NOTE: This software was tested on Windows Vista, Mac OS 10.6 and Linux Mint 9. While it may (and should) run on similar platforms I have not been able to test this. Please remember that this software is provided “as is” and without any sort of warranty. Use at your own risk.

It’s no secret that while Java possess probably the most widely distributed, cross-platform, and common user interface libraries, graphical Java applications on the whole simply stand out for the wrong reasons. Whether the GUI comes in the form of the Abstract Window Toolkit (AWT) or Swing, each can be far from pretty and often do not mesh well with the platform they are being run on. For instance, running an AWT or Swing application can be an almost alien experience, no matter what operating system you are using, because neither uses the native control widgets. Even AWT, being a ‘thin’ layer above the native controls, often looks completely bizarre. On Windows Vista AWT looks more like Windows 3.1 than anything else. Thankfully there is a nice alternative in the IBM created (and now Eclipse maintained) SWT.

The Standard Widget Toolkit, or SWT, passes all GUI rendering responsibilities onto the host operating system. This allows for some interesting advantages like hardware rendered drawing for free (as an example). It also provides for a native look and feel because its actually using the real native widgets. So when run on Windows it looks like a regular Windows application and when run on Linux it looks like a Linux (GTK+) application. It also works on the Mac as well as a few other obscure platforms.

Unfortunately because the application is now creating widgets outside of the JVM you are suddenly responsible for freeing the memory. There is no automatic garbage collection in the world of SWT. It’s not all bad however as freeing a parent object, like a window (referred to as a shell in SWT lingo), automatically frees all of its related child objects as well. Simply call the .dispose() method and 9 times out of 10 you are done.

Another other caveat is that you will still need to package the correct swt.jar file for your target platform. For instance Windows has its own version of swt.jar, as does Linux, and Mac, and so on and so forth. While this is rather annoying it does offer some interesting trade-offs. For instance you do not need to recompile your code just because you want to run it on a different platform; simply swap out the swt.jar file and watch as the exact same code generates completely different native GUIs. I even wrote a simple program that first checks what platform it is being run on and then downloads the correct swt.jar file before launching the GUI. This makes releasing the exact same package very simple.

So how do you start using SWT? Head over to http://www.eclipse.org/swt/ and download the newest stable version for your platform of choice. Depending on how you will be programing, all you have to then do is add the enclosed swt.jar to your class path. If you’re using Eclipse, or a similar IDE, you can simply add the source as either part of you project, or as a separate referenced one, and take full advantage of the auto-complete as well. Perhaps I’ll get around to posting a more thorough how-to guide at some point in the future.

Like most things in software SWT is not perfect. There are still other challenges to overcome, such as creating each individual platforms’ unique user experience to compliment their native GUI toolkits. That said if you’re looking for a way to leverage the widespread nature of Java, while still creating an application that looks like it belongs, SWT might just be what you’re looking for.