## Using SWT with JRuby

JRuby is a Java implementation of the Ruby programming language. One of the strengths of a Java implementation is that Java libraries can be used within Ruby code, the Ruby way (and that is cool, as we have seen!); the weaknesses are that this means that the code is a lot slower to execute, and similar to what happens with Jython (the Java implementation of Python) the Java implementation lags behind the “official” version. This is obviously to be expected, and in fairness to the JRuby guys, they are pretty reactive!

This post will describe how to use SWT with JRuby. It is written for Ubuntu, but more than likely very similar on other platforms.

### Setup

First, get JRuby: I’ll be using 1.4.0 (which was released last month). Install it in a location that I’ll be calling $JRUBY_HOME. Add $JRUBY_HOME/bin into your $PATH so that you can run the jruby command: sebastien@kilkenny:~$ jruby --version
jruby 1.4.0 (ruby 1.8.7 patchlevel 174) (2009-11-02 69fbfa3)
(Java HotSpot(TM) Client VM 1.6.0_12) [i386-java]


Get SWT from here (this article will be using SWT 3.5.1 for Linux), and extract swt.jar into \$JRUBY_HOME/lib: that’s a quick way of making the jar available to JRuby.

Once everything is set up, we can begin with a very simple example.

### First Quick Example

(I have posted the following example as a snippet on dreamincode at the time of writing, it is still awaiting approval)

require 'java'

display = org.eclipse.swt.widgets.Display.new
shell = org.eclipse.swt.widgets.Shell.new(display)
shell.setSize(800, 600)
shell.setText("First Example")

shell.setLayout(org.eclipse.swt.layout.RowLayout.new)
org.eclipse.swt.widgets.Button.new(shell, \
org.eclipse.swt.SWT::PUSH).setText("Click me!")

shell.open
# Classic SWT stuff
while (!shell.isDisposed) do
end
display.dispose


This opens a nice and simple window:

Typical to JRuby, the first thing we do here is require 'java' to be able to call Java classes from our ruby code. And then, from then on, it is all SWT code: create a Display class, and with this Display, create a new Shell (window), whose size is 800×600. Then set the layout as RowLayout, and add a Button. Make the window visible with open, and the rest of the code is pretty much common SWT code to keep the window open until the application is shut down, at which point, the display is cleared up.

As you can see from above, the only tricky things are:

• the fully-qualified names of the Java classes have to be provided (we’ll see a way of avoiding this in the next example);
• static variables have to be accessed with ::

### And Now, For a More Advanced Example

The more advanced example will read the RSS feed from weblogism, and fill in some labels, and put items in a table. Ruby provides a neat rss package, and good example of how to use it can be found here.

One of the things you’ll want to look at is the repetition of the Java packages: this is a bit tedious, so we have to find a way of avoiding this. One way is to call include_class to include the Java classes by their name. One trick is to list all the classes of a given package in an array, and to include them with an iterator:

%w(Display Shell Label Table TableColumn TableItem).each do
|c|
include_class "org.eclipse.swt.widgets." + c
end


With this knowledge, I can now give you the example:

require 'java'
require 'open-uri'

include_class "org.eclipse.swt.SWT"
# Neat little trick to include several classes from the same package.
%w(Display Shell Label Table TableColumn TableItem).each do
|c|
include_class "org.eclipse.swt.widgets." + c
end
%w(GridLayout GridData).each do
|c|
include_class "org.eclipse.swt.layout." + c
end

# uppercase variable is constant

def initialize

@display = Display.new
@shell = Shell.new(display)
@shell.setSize(800, 600)
@shell.setText("Second Example")

gridlayout = GridLayout.new
gridlayout.numColumns = 2
@shell.setLayout(gridlayout)
name = Label.new(shell, SWT::NONE)
name.setText("Name:")
name.setLayoutData(GridData.new(GridData::VERTICAL_ALIGN_END))

Label.new(shell, SWT::NONE).setText("URL:")

table = Table.new(shell, SWT::MULTI | SWT::BORDER | SWT::FULL_SELECTION)
table.setLinesVisible(true)

gridData = GridData.new(GridData::FILL_BOTH)
gridData.horizontalSpan = 2
table.setLayoutData(gridData)

# Set the header of columns.
columns = %w(Title Date Author)
columns.each{ |h| TableColumn.new(table, SWT::NONE).setText(h) }
|i|
item = TableItem.new(table, SWT::NONE)
item.setText(0, i.title)
item.setText(1, i.dc_creator)
item.setText(2, i.date.to_s)
puts i
end
# Each column then needs to be packed to display properly
for i in 0...columns.size
table.getColumn(i).pack()
end

end

def show
@shell.open
while (!@shell.isDisposed) do
end
@display.dispose
end

def get_messages
# and parse.  "false" means "no validation"
end
end



This simple snippet gives the following window:

### Conclusion

The examples above are not that far away from the Java snippets proposed on the SWT web site. This shows how JRuby can be easy to learn if you are already familiar with Java – and you get to play with a few syntactic niceties like the iterators that ruby brings in.

However, it is true that performance can still be an issue on some big apps, but hopefully this will improve in the coming months.

## Comment

 Name Remember Email Website Message Textile help