How to use SWT with Java 8

java8 logo 281x300 How to use SWT with Java 8As 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

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:

  • VerifyListener
  • TraverseListener
  • TouchListener
  • PaintListener
  • ModifyListener
  • MenuDetectListener
  • HelpListener
  • GestureListener
  • DragDetectListener
  • DisposeListener
  • ArmListener.

Arrays

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 ) );

Display#(a)syncExec

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.

[ Now go find some tools to hack your workflow: Eclipse Tools. | Running a mission-critical system? Keep it running smooth with our Production Support. ]

One Response to “How to use SWT with Java 8”

  1. Moritz Post says:

    Nice tips.

    To print the visibility of each child you can even further simplify the example above to

    Stream.of( parent.getChildren() ).map( Control::isVisible() ).forEach( System.out::println );

    Or if you would want to only get the visible children you could use:

    Stream.of( parent.getChildren() ).filter( c -> c.isVisible() ).forEach( System.out::println );

    An interesting detail is the usage of the Stream.xx factory methods. It takes an array via its varargs so you don’t have to create another list.

One response so far

Written by . Published in Categories: EclipseSource News, Editors choice, Planet Eclipse