Want to stay on top? Ruby Weekly is a once-weekly e-mail newsletter covering the latest Ruby and Rails news.
     Feed Icon

JRuby + SWT = Future Cross Platform Ruby Desktop App Development?

By Peter Cooper / November 9, 2006

Rubyswt

(Disclaimer: I'm no Java wiz, so if I get anything wrong about Java or its libraries, post comments!)

The SWT (Standard Widget Toolkit) is a GUI widget toolkit for the Java platform. Unlike AWT and Swing, it uses the local operating system's own controls. This means you can develop Java apps that 'look native' on multiple platforms. The popular Eclipse IDE uses SWT to work and looks graphically native on multiple platforms (as does Azureus). SWT is also, reputedly, faster than the other alternatives. Sounds great for developers, right? Java developers.. sure.

I decided SWT was too good an idea to not investigate, so I downloaded JRuby 0.9.1 (a Ruby interpreter written in Java and which provides access to Java classes from Ruby) and set to work. All I had to do was copy the swt.jar and supporting files for my platform into the jruby/lib folder, add "-Djava.library.path=$JRUBY_BASE/lib" into the Java call in the bin/jruby helper script.. and then I could write and run code like this:

require 'java'

module SWTTest

  include_package 'org.eclipse.swt'
  include_package 'org.eclipse.swt.layout'
  include_package 'org.eclipse.swt.widgets'

  Display.setAppName "Ruby SWT Test"

  display = Display.new
  shell = Shell.new display
  shell.setSize(450, 200)

  layout = RowLayout.new
  layout.wrap = true

  shell.setLayout layout
  shell.setText "Ruby SWT Test"

  label = Label.new(shell, SWT::CENTER)
  label.setText "Ruby SWT Test"

  Button.new(shell, SWT::PUSH).setText("Test Button 1")

  shell.pack
  shell.open

  while (!shell.isDisposed) do
	  display.sleep unless display.readAndDispatch
  end

  display.dispose
end

This works on OS X (screenshot of result is at the top of this post) but it's all generic so if you can get JRuby and the SWT JAR and support files for your platform, this same code will render a native looking window with a label and button control on whatever platform you're running. The major downsides so far are that it's a bit unstable (if I move the window much, the app crashes) and I can't seem to create events for the controls, although I think this might be due to my lack of Java nous. Also.. it's an experimental piece of software running on an experimental compiler, so it's far from ready for real use, and there are undoubtedly better solutions, but if you like to hack...

Comments

  1. Dr Nic says:

    Perhaps write a JRuby -> Java converter for the production code :)

  2. Johannes Rudolph says:

    I started a GUI builder framework two months ago which makes it easy to build a user interface using SWT and JRuby.
    Using the fast and crossplattform SWT together with the ruby syntax is really a powerful combination...

  3. murphee says:

    There's a library that's using the builder concept to create SWT GUIs with JRuby:
    http://sweetgui.rubyforge.org/doc/

  4. Danno says:

    I dunno, that code looks pretty 'blech', very not Ruby.

    Compare: http://www.oreillynet.com/pub/a/mac/2004/07/27/ruby_pt3.html

  5. Alan says:

    There is also a company that has a Flash-based replacement for all SWT widgets (and the Flash can be customized with XML).

    http://inspyre.sesma.com/fclspyre.htm

    They have a nice screencast of the product working

    http://inspyre.sesma.com/evaluation/screencast/fling.htm

  6. Nick Sieger says:

    @DrNic: most of the work is probably being done by Java here, so you may not need to ever convert it! That's the best thing about using Ruby here, it's just the gluing together of the SWT comps.

    @Danno: those kinds of mini-DSLs should be easy to create as light wrappers around SWT. With a little bit of work Peter's example could look more like this:

    require 'java'

    module SWTTest
    Display = org.eclipse.swt.widgets.Display
    Shell = org.eclipse.swt.widgets.Shell
    RowLayout = org.eclipse.swt.layout.RowLayout
    Label = org.eclipse.swt.widgets.Label
    Button = org.eclipse.swt.widgets.Button
    Display.app_name = "Ruby SWT Test"

    display = Display.new
    shell = Shell.new(d) do |sh|
    sh.set_size(450, 200)
    sh.text = "Ruby SWT Test"

    sh.layout = RowLayout.new do |layout|
    layout.wrap = true
    end

    Label.new(shell, SWT::CENTER).text = "Ruby SWT Test"
    Button.new(shell, SWT::PUSH).text = "Test Button 1"
    end

    shell.pack
    shell.open

    while (!shell.isDisposed) do
    display.sleep unless display.readAndDispatch
    end

    display.dispose
    end

    Note that the block-initialize stuff doesn't exist, but that's the glue that should be easy to write. JRuby does allow you to add methods to java objects (they just aren't visible from Java, yet).

  7. Danno says:

    Hmm... well, I hesitated to even post the TK stuff because while it's more Rubyish, it's still not as Ruby as I want to see.

    I dunno, I'm not going to be doing any windowing toolkit wrappers in the near future, so I probably shouldn't complain.

  8. Peter Cooper says:

    Well yeah, it was only a quick trial.. you get things working, then you make them nice ;-)

  9. Hendy Irawan says:

    Hi Peter, I agree with you that JRuby + SWT (or Swing) is likely to be the future of cross-platform desktop application development using Ruby.

    IMHO, there's little reason why we shouldn't use [some of] the Java platform to make our Ruby GUI desktop programming easier. After all, Ruby programming is all about productivity. There are other alternatives though, such as FXRuby (uses FOX, not native), and wxRuby (which uses wxWidgets, the "de-facto" cross platform native GUI toolkit).

    A few downsides seem be lack of tools (such as visual form designer) and stability. I've researched quite a bit on this:

    http://web2withrubyonrails.gauldong.net/2006/11/07/the-best-cross-platform-toolkits-and-environments-a-journey/
    http://web2withrubyonrails.gauldong.net/2006/11/08/the-search-for-cross-platform-toolstack-the-research/

    [Spoiler] The current conclusion was: JRuby+Java isn't very feasible yet for general GUI programming, so I concluded that Java+Swing/SWT better for productivity. JRuby+Swing/SWT is a very attractive alternative and I can bet in the near future it'll be a very popular way of developing GUI cross-platform desktop applications. (do you also imagine writing J2ME applications using Ruby?) ;-)

  10. Graham Lea says:

    Some comments on Java, as requested. :)

    >Unlike AWT and Swing, it uses the local operating system's own controls.

    AWT also uses the local operating system's controls.
    When using the system look and feel, Swing will (on Windows at least) uses the same Windows code to render controls as Windows uses, so they look identical.

    >This means you can develop Java apps that 'look native' on multiple platforms.

    There are lots of people that think that this is important, but there are also a lot that think it doesn't matter, and growing evidence that users don't care. For instance, Windows Media Player has a very different look to other Windows programs and people are quite happy to use iTunes on Windows without ever saying "this looks funny!"

    >The popular Eclipse IDE uses SWT to work and looks graphically native on multiple platforms (as does Azureus).

    True, but a Swing app also looks pretty darn close to native on most systems.
    Eclipse also has its own custom look for tabs (on Win at least), and probably some other components. This suggests that, while its developers espouse that platform fidelity is all-important, they admit by their actions that sometimes it's better for an app to look good than to match the platform.

    >SWT is also, reputedly, faster than the other alternatives.

    There is a lot of SWT supporters who will say that SWT is faster and a lot of Swing supporters who will say Swing is faster. But think about this: Java is fast enough to run full-screen, 3D network games. If your Java GUI isn't performing it's not becuase your framework is slow but because you don't really know what you're doing.

  11. james hoskins says:

    I was looking through the transcripts of a talk given by Charles Nutter to the Gateway Java Users Group and noted some irb/gui stuff in swing - including a listener!

    You can find a summary here:

    http://www.infoq.com/news/2006/11/gateway-jug-jruby

    And the code examples on Alex Miller's blog.

  12. Greg says:

    When I think of cross-platform GUI, I think of Java's various GUI toolkits and I shudder. Then I think of Tk and company and shudder even worse. Then I remember Qt. Qt is an elegant, well-designed cross-platform toolkit which is primarily a GUI toolkit but includes a variety of other pieces (DB drivers, network API, etc.) as well. When it comes to implementing a non-web GUI on any platform, even if the app need not be cross-platform, my first choice is Qt. Even programming in C++, which is Qt's native language, it is my first choice.

    But there's QtRuby. I can write my cross-platform GUI app in the language of my choice with the GUI toolkit of my choice. It doesn't even make it feel like I'm working in some hybrid of C++ and Ruby, since it affords a variety of Ruby niceties including using blocks for slots (event handlers). Hurray! Its only failing is that it is GPL rather than LGPL, which means that even purchasing a license from TrollTech does not free your from the obligations of the GPL.

  13. Rune Hammersland says:

    Greg: Buying a license from TrollTech will give you a commercial license which gives you about the same things as the BSD license (if I'm not mistaken). You can have your application GPL, which means it's free to use QT, or you can distribute it under another license, but then you have to pay for the commercial QT license. You're not required to use GPL in both cases.

  14. Pingback: rukh.de

  15. Charles McKnight says:

    @Hendy Irawan

    I can't imagine writing J2ME apps at all, let alone in JRuby+SWT. The JVMs are not standardized across devices so you end up porting everywhere. If I have to go to that degree of work, I'll write a code generator to kick out a native binary in 'C'. The mobile operators are pushing for a "standard" JVM, but there will be a noticeable gap between having the "standard" and having "standards-based" implementations across all platforms.

    FWIW, even with the faster processors on mobile devices and more memory you'll find that most developers who write desktop applications write horribly bloated and inefficient mobile applications (doesn't have as much to do with language as mindset) since they are used to far more CPU processing power and memory than is available on most mobile devices. It's one area that the "old" people who had to get by with 8K or less memory really have an advantage in their thinking (IMHO).

  16. Cliff says:

    Why? Why purchase a jet plane to visit your next door neighbor? I have nothing against Ruby or JRuby but it puzzles me why someone would pickup a whole new language and API just to do something that you can do by extending Java. Groovy is perfect for writing GUIs in either Swing or SWT. (Admittedly I have not seen a SWTBuilder I think it would be somewhat simple to implement.) I see way too many articles comparing Ruby to Java all of which suggests that the language is the problem. They each overlook the simplest solution (Use a dynamic language) in favor of tossing the baby with the bath water and bringing on a whole new platform and\or API. The above example could be implemented just as neatly if not neater with Groovy. FWIW, I do appreciate the article. It just bothers me that no mention has been made of a potentially evquivalent or better solution.

  17. Peter Cooper says:

    Cliff: Thanks for the valuable comments. Just to comment on the point of the article.. really, I know next to nothing about Java, and just wanted to see if JRuby was at a stage where it could interact with some cool Java technologies I'd heard about. I'm sure there are definitely far better things to be doing, especially if you're already a Java user, but I wanted to try out something experimental Ruby-related that I hadn't seen anyone else do before (since this is a Ruby blog and all :))

  18. Jan Erik says:

    Here is a Javascript + XML example so that you can compare.

    http://fabric.no/weblog/archives/2006/11/javascript_jfcpark_vs_jruby_sw.html

  19. Paul King says:

    Here is a similar example using Groovy (both with and without the builder notation):

    http://groovy.codehaus.org/GroovySWT

Other Posts to Enjoy

Twitter Mentions