How to use SWT with Java 8
As you might have noticed, Java 8 was released last week ;). Most programers consider Java 8 the biggest change to the Java programming language ever made. This is mostly because of lambda expressions, default methods and streams. As an SWT/RAP/Tabris coder, the first thing that came to my mind was: “How can this make my SWT code better?”. This blog will show you how to use the new Java 8 features with SWT.
Events are heavily used in SWT for handling user interaction on UI elements. As you might know, there are two kinds of events: typed and untyped. Wouldn’t it be neat to use lambda expressions for event handling? The cool thing is, with untyped events this can be achieved easily out-of-the-box. What you need to know is that every anonymous implementation of a “Functional Interface” (an interface with only one method) can be exchanged using a lambda expression. For a SWT Selection event on a button, this might look like this:
Button button = new Button( parent, SWT.PUSH ); button.addListener( SWT.Selection, event -> System.out.println( "Button was selected" ) );
For typed events this is only possible with a small number of the listeners, because many of them have more than one method. Listener interfaces with only one method are:
SWT is not the newest Java API. For this reason you will probably deal with arrays a lot. Java 8 brings concepts like default methods and streams. These are nice when dealing with collections. So, how can we make use of them in our SWT code? The answer is pretty simple: “Make a list out of the array!”. When doing this, you can use lambdas, streams and e.g. the forEach default method for your controls. A simple example can look like this:
// printing child visibility Arrays.asList( parent.getChildren() ).forEach( child -> System.out.println( child.getVisible() ) ); // hiding each visible child Arrays.asList( parent.getChildren() ).stream() .filter( child -> child.isVisible() ) .forEach( child -> child.setVisible( false ) );
When dealing with threads in SWT, you need to do UI modification in the UIThread because of the Apartment threading model of SWT. For this reason you will end up nesting anonymous
Runnable implementations, which always sucks. But wait a minute! A
Runnable is also a “Functional Interface” because it has only one method, right? So, why not use lambdas for it? It could look like this:
Display.getCurrent().asyncExec( () -> System.out.println( "async exec" ) ); Display.getCurrent().syncExec( () -> System.out.println( "sync exec" ) );
After migrating some of our UI code to use Java 8, I can say that thanks to the ideas above, I ended up with much cleaner code. If you have other ideas on how to use Java 8 features with SWT, please don’t hesitate to post a comment.