Skip to main content

Cross-platform development with JRuby and Swing

Develop desktop applications rapidly with the Monkeybars JRuby Swing library

James Britt, Principal, Happy Camper Studios
James Britt
James Britt is a principal at Happy Camper Studios, a Ruby application development company in Phoenix, Arizona. An active voice in the Ruby community, James has presented at Ruby conferences in the United States and Europe and written numerous technical articles for publications such as Dr. Dobbs and Linux Journal. He wrote most of the Web development section in Hal Fulton's book, The Ruby Way, 2nd ed. James also created and maintains Ruby-doc.org, the main documentation site for the Ruby language.

Summary:  In addition to building Web and console applications with Ruby, you can write complex GUI desktop applications that run unmodified on multiple platforms. Thanks to JRuby, a robust alternative to the traditional C implementation of Ruby, Ruby GUI toolkits can use UI tools available to the Java™ platform. This article introduces Monkeybars, a library that uses JRuby and Swing for building applications, and takes you through an example application.

Date:  07 Oct 2008
Level:  Intermediate PDF:  A4 and Letter (69KB | 21 pages)Get Adobe® Reader®
Activity:  13163 views
Comments:  

Ruby is currently best known as a programming language for building Web applications, primarily with the Ruby on Rails framework. However, the language is more than capable for developing graphical desktop applications as well. In this article, you'll learn more about using Ruby for the desktop, and you'll work through a detailed example that uses Monkeybars — an open source library based on Swing and JRuby — to create a GUI desktop application.

Ruby for the desktop

The standard Ruby distribution includes code for bindings for Tk, an open source, cross-platform set of widgets for creating graphical desktop applications. This can be extremely handy. But when you install Ruby from source code, you need to be sure you also have the Tk dependencies and make sure the compilation settings include Tk. If you install Ruby on Windows® using the excellent "one-click" installer package, you still must take extra steps to have Tk working, because it no longer supports automatic installation.

Even with Tk set up for Ruby it is somewhat clunky. Tk applications often look like Tk applications; depending on the target platform they can look rather ugly. And trying to create complex interfaces is daunting. Tk is best used for smaller GUI needs.

Available toolkits

The weakness of Tk has prompted the development of other GUI toolkit options for Ruby (see Resources for relevant links). Some of the notable choices are:

  • FxRuby: FxRuby is a Ruby binding for Fox, a GUI toolkit written in C++. It is available for installation using RubyGems. A binary gem is available for Windows; the gem for other platforms requires you to compile native code.

  • WxRuby: WxRuby is a binding for the cross-platform wxWidgets C++ GUI toolkit, which lets you create native-looking desktop applications. It is available for installation as a gem.

  • QtRuby: QtRuby gives you Ruby bindings to the Qt toolkit (the one used in the KDE desktop system). A gem is available for the Windows installation, but only source code for other platforms.

  • GTK-Ruby: GTK is the UI toolkit used in GNOME; you need to compile native code to get it running.

  • Shoes: Shoes is a recent entry into the Ruby GUI widget world. Unlike the other toolkits mentioned in this list, it is designed specifically for Ruby. It is available for installation using platform-specific installers.

  • Swing: Swing? Yes, Swing, the GUI library that is bundled with every installation of a Java runtime environment. If you run JRuby, then you can use Swing.

All but one of these are GUI or widget libraries written in C or C++, with bindings that allow them to be called from other languages, such as Ruby, Python, and Perl. In almost all cases, you face a number of considerations, such as installation and distribution.

Considerations for selecting a GUI library

Which GUI tool set you decide to use depends, of course, on your particular needs. Criteria to consider include:

  • A rich set of widgets or components
  • Solid implementation
  • Availability on multiple platforms (mostly Macintosh, Win32, KDE, and GNOME)
  • Native look-and-feel for hosting platform
  • Whether or not it is actively maintained
  • Ease of creating custom widgets
  • Nonrestrictive license
  • Affordable cost
  • Existing frameworks and libraries to speed development
  • Mature IDEs and form layout tools
  • Testing tools and frameworks
  • Ease of packaging and deployment

If all you want is to toss up the occasional message box, or ask a user for some simple input, almost any of the toolkits I've listed will do. For simple requirements, you are likely better off focusing on platform availability, a suitable range of widgets, and appropriate cost. If you plan to distribute your application, you'll want to check the toolkit licensing. You also must be sure either that the user already has the required environment or that you can easily bundle all the needed libraries and widgets in either a stand-alone application or an installation package.

Once you move to complex applications, though, the requirements get tougher. For any application that goes beyond a few simple forms, you almost certainly want to have a form-designer tool. You also want a rich set of available widgets; you're usually better off reusing an existing date picker or file browser component, for example, than writing your own.

Each of the various C-based Ruby GUI toolkits has its share of good qualities, but none of them has emerged as a clear winner. They offer no obvious choice for general Ruby cross-platform desktop development. To varying degrees, they all have issues with installation, documentation, design tools, packaging, and deployment. Notably, none of them can beat, feature-for-feature, the one non-C option.


Leveraging Java technology

JRuby is an implementation of Ruby for the Java platform (see Resources). It allows you to execute Ruby code through the JVM. Ruby code running under JRuby can also load and use Java libraries, including Swing.

Some arguments against JRuby + Swing

On the bright side, Swing components abound; on the dark side, they are Swing objects; you can load them into your Ruby code, but you need to know their assorted APIs and syntactical quirks. Swing documentation and examples are copious, but unless and until people write Ruby wrappers around these components, there is no getting around having to get your hands a bit dirty with some raw Swing code.

A second common objection is that Swing may not look quite as slick or native as, say, Qt. But things are not what they used to be, and Swing can now look quite good.

Weighing the Java platform against a C-based tool, you'll have to make some choices and decide what's most important. For example, Swing is completely free to use, whereas Qt has various costs and restrictions for commercial and open source applications. On the other hand, the look-and-feel of the Qt components may be better for your program.

Several aspects of Java the platform make JRuby a good choice:

  • It is solid and well tested
  • It has strong community and vendor support
  • The documentation is good and plentiful
  • You have an excellent choice of IDEs and UI layout tools
  • It's free to use (both in cost and license)
  • The Java runtime is probably already installed on users' machines

If you write an application in (J)Ruby and use Swing for the UI, you need only ensure that the user has a recent version of the Java runtime and package your application to include the JRuby JAR file. And there's a Ruby tool for JRuby application packaging, making that aspect a nonissue.

Developer options for (J)Ruby + Swing

There are a number of options for using Swing from Ruby:

  • Raw, hand-coded, in-line calls to Swing objects: In the simplest case, you can refer to Swing objects much as you would any other Ruby object:
    panel = Java::javax::swing::JFrame.new("JRuby panel")
    panel.show

  • "Builder" and domain specific language (DSL)-style libraries: Constructing panels and forms and then adding components all in hand-rolled code can get tricky quite fast. Some libraries exist to make the Swing interaction more Ruby-like. For example:
    • Cheri::Swing uses Ruby block syntax to generate the Swing code.

    • Another library, Profligacy, offers a Ruby wrapper around the raw Swing calls to help you write more Swing code with less raw Java code. You still need to get familiar with the Swing API docs to make proper use of the Swing components.
    Both of these approaches presume the creation of panels, forms, and layouts using hand-crafted code. Although an improvement over doing this with straight-up Swing code, they still suffer from an inability to handle complex user interfaces.

  • The "we don't care where the Java class came from" approach: A third approach is simply to punt on trying to ease the creation of Swing objects using Ruby code and start from the assumption that a compiled Java class for the Swing objects already exists.

The last is the approach taken by the Monkeybars library (see Resources). A number of very good, free, graphical Swing UI layout editors exist. As with the use of the previously mentioned GUI toolkits (such as Fox and GTK), you don't need a UI editor for the occasional dialog box. But it's hard to beat such a tool for anything more than that, and it's pointless to skip these tools and code the UI by hand for a sophisticated desktop application.

Monkeybars

The Monkeybars project grew out of product development by David Koontz at Happy Camper Studios and has evolved based on experience trying to create testable, maintainable, complex Ruby desktop applications. It is actively maintained and completely free to use as you see fit.

Monkeybars is an open source Ruby library that connects existing Java Swing classes (that is, compiled Java classes that define your Swing UI) to Ruby code using a form of the Model, View, Controller (MVC) design pattern. MVC aims to separate view logic and UI components from application logic.

Because it uses the Java language and Swing libraries, Monkeybars builds on mature, robust technology. Unlike other current Swing libraries for JRuby, it is well-suited for constructing large, complex, multipaneled applications. As you'll see, creating a Monkeybars application entails some overhead, so it might not be your best choice for simple forms. But it's a reasonable choice for a JRuby desktop application of any complexity when you need:

  • Reliable cross-platform deployment (assured to the degree that the user has a recent JVM installed)
  • A large choice of UI widgets of arbitrary complexity
  • Possibly complex UI form and panel construction and interaction

Why Swing instead of SWT?

Monkeybars uses Swing instead of the Standard Widget Toolkit (SWT) because:

  • Swing is a part of Java programming; users who have Java programming also have Swing.
  • Swing allows for more fine-grain control of component behavior.
  • Swing components offer more flexibility over how components can look.

Like Profligacy, Monkeybars does not hide the Swing API. Nonetheless, because it works with compiled UI classes, you can make full use of any tool or application to generate the actual layout. Depending on your application's complexity, it is almost inevitable that at some point you'll need to reference Swing component API documentation and code examples to know what to do in your Ruby code. (But thanks to the nice integration of JRuby and Java libraries, you can easily wrap such Swing code in a Ruby API for easier reuse.) Programs built using Monkeybars can be arbitrarily complex, but you can follow some basic patterns to keep the code manageable.

The Monkeybars approach to MVC

The MVC pattern has a long history, with numerous variations. With Monkeybars, the basic premise is that for each Swing frame (that is, the UI object holding assorted components or widgets; in some cases this can be a modal panel) there are three Ruby files: a model, a view, and a controller. The model class holds the essential business logic and manages the data corresponding to that part of the application. It should be ignorant of any view or controller code that exists as a means to interact with the model. Keeping view and controller references out of your model makes it much easier to develop and test.

The view is another Ruby file with a reference to a specific Java class containing the compiled Swing code. The view manages the interaction of Swing components with model data. The view can have direct contact with the model, but it also works with a copy of the model as a means of passing data to the controller. This is important to keep in mind when you design your model class, because it ends up serving a dual purpose. The primary instance of the model is keeping long-term state and providing application logic; the copy used by the view is essentially a disposable data-access object. Models should be relatively cheap to instantiate, with shallow accessors provided for any data used by the view.

The view does not have direct contact with the controller. Instead, a signaling system is in place to abstract the interaction of controller and view. This decoupling makes it easier to test your views and controllers.

This description is deliberately simplified and omits various details. Under the hood there is closer interaction between view and controller; the infrastructure needs the means to coordinate behavior. The goal of Monkeybars is not to tie your hands but to assist you in creating testable, maintainable code. As a developer, though, you are free to bypass the intended API if you see fit.

The controller class is where you define handlers for Swing events (such as button clicks and text-field changes) and control the state of the model. The controller keeps a reference to the primary instance of the model. It does not communicate directly with the view.

When a controller wants to get data from the view, the view provides a copy of the model populated with the current UI contents. The controller can then decide to update the primary instance of the model with this data or take some action based on these values. The controller can also tell the view to update itself and pass back updated values. You'll see this in action in the example application.


An example JRuby Swing application using Monkeybars

To get a feeling for creating a desktop application with Swing and Ruby, I'll take you on a tour through a simple program created using Monkeybars. (See Download for a link to the complete example source code.)

Getting started

To get started, you need to have a few things in place:

  1. Get a copy of the jruby-complete.jar (see Resources for a download link).

  2. Install the Monkeybars library. You can install it as a gem:
    sudo gem install monkeybars
    

    You can also grab the current source code from the repository on gitorious.org (see Resources).

  3. Install the rawr gem:
    sudo gem install rawr

    Strictly speaking, rawr is not required for writing a Monkeybars application, but it provides a number of useful rake tasks for turning a JRuby application into an executable JAR file. This article's example uses it.

Application basics

The example application is a "flash card" program that reads in a text file that defines a number of "cards." It loops until shut down, periodically showing and hiding itself for brief periods. Basically, it's a tool for learning. For this example, the cards are a set of German vocabulary words and phrases. The program also reads a configuration file that defines the location of a cards-definition file and a few settings (show/hide speed, window size).

The goals of this example are to:

  • Show the use of Monkeybars code generators, which automate the creation of common files
  • Show the basic structure of a Monkeybars application
  • Demonstrate the creation of each part of the Monkeybars MVC tuple
  • Show how Monkeybars handles the mapping of application data to UI components
  • Show packaging the application as an executable JAR file

Using the Monkeybars application generator script

Once installed, Monkeybars provides a command-line script to create an initial set of application files. To start a new Monkeybars project, execute the monkeybars script that is installed with the gem. Name your project monkey_see:

$ monkeybars monkey_see

This creates a new directory at the given path (or in the current directory if you only give an application name) and adds core files and directories for the new application.

Using rawr to bootstrap the code into the Java environment

rawr is another Ruby library that grew out of Monkeybars. It handles assorted packaging tasks and provides a command-line script for creating a base Java class that a Monkeybars application can use to allow execution as a Java program (as opposed to running the application as a Ruby program via JRuby).

You use it with your Monkeybars application by going to your project directory and executing the rawr script:

$ cd money_see; rawr install

Using Monkeybars rake tasks to generate files

You've seen how Monkeybars splits things up into model, view, and controller. The convention is to place these files into the same directory. To help this along, Monkeybars provides a rake task to generate these files. You can create any one of the three or a full set (the more common case):

$ rake generate ALL=src/flash

This command creates a subdirectory called flash under src/, with three files: flash_controller.rb, flash_view.rb, and flash_model.rb. The first two have bare-bones classes that inherit from base Monkeybars classes. The model code does not; Monkeybars makes no assumptions about how you manage your application logic and data; that is entirely up to you.


Creating the UI

For the application's interface, you need a Swing class that displays the flash-card data. How you create this is up to you; nothing in Monkeybars ties it to any particular UI tool or Swing code generator. By convention, the Swing file gets placed in the same directory as its related tuple (src/flash/FlashFrame.java). You need to know the class package so you can pass it on to the view class. (Use the flash package and name the class FlashFrame.)

Your screen layout should look like Figure 1:


Figure 1. The application's screen layout
The application's screen layout

A few key points: You should use a JTextPane for the flash-card content so you can use HTML to format the rendered text. You should also use sensible names for the text pane and the button. It just makes it easier when you're working with the view to know something about the UI components. The program code is in Ruby, so use Ruby method-naming conventions: call the text pane card_pane and the two menu items edit_menu_item and quit_menu_item. Give them accelerator keys, too.

The name of the frame itself is not important; the view class can reference the components directly by name.

Defining the model

The model manages the application logic and data behind a given UI. A Monkeybars program generally has a model for each Java form. The example application has a single model to handle the flash-card data. The model code needs to be able to load data from a known location and offer a public method to provide that data.

For simplicity, you'll store the data in a text file in a subdirectory from where the application is running. Rather than hand-code HTML, you can use Textile markup and transform it using the RedCloth Ruby library. Each card entry will be separated by a delimiter string.

Using third-party libraries

Textile is a text markup format that is intended to define HTML using simple plain-text conventions. For example, to indicate <em>italicized</em>, you instead write _italicized_. RedCloth is a Ruby library, available as a gem, that converts Textile-formatted text into HTML.

Rubygems makes it quite easy to install and use third-party libraries, but because you'll want to package your code in a JAR and potentially distribute it, you need to be sure that all code is included with the application. To do this, unpack the RedCloth gem and copy the redcloth.rb file to the project's ruby/lib/ directory:

$ cd /tmp; gem unpack RedCloth

This creates /tmp/RedCloth-3.0.4 /(unless you have a different version of the gem installed). Copy /tmp/RedCloth-3.0.4/lib/redcloth.rb to the lib/ruby/ directory of your monkey_see project.

In general, any Ruby libraries that are not core parts of your application should go (as a convention) under lib/ruby/. If you are using gems, you need to unpack the actual library files and add them to your project. Later in this article, you'll see how to tell your program how to find these files.

Key model methods

The load_cards method handles reading in the text file from disk, splitting out each card, and assigning the results to the @cards instance variable.

A select_card method picks a card at random and assigns it the @current_card instance variable. You'll use attr_accessor to define methods for reading and setting this variable.

You'll arrange it so that whichever card is being displayed in the UI can be edited in place. After editing, the update_current_card method takes the contents of @current_card and reinserts it into the @cards array. A save method writes the @cards array back to disk.

The value of the current_card method is what you want to render, and to do that, you need a view class.

Defining the view class

A Monkeybars view class is the owner of the Java Swing class. If you open up flash_view.rb, you can see that it invokes a class method, set_java_class. This should be set to the Swing class defined for this view. In your code, this is flash.FlashFrame.

In general, a Monkeybars view class needs to do three things:

  • Pass data in and out of the Swing components
  • Manage assorted view-centric behavior (such as size and position)
  • Respond to signals sent from the controller

Mapping data

Monkeybars provides a map method that allows you to define how model methods are wired up to Swing controls. The simplest usage connects a UI component method and a model method:

map :view => :card_pane.text, :model => :current_card

This mapping uses the default behavior of making this a direct, two-way association. That is, the results of the card_pane component's text method are passed to the model's current_card= method. When the view is updated from the model, the process is reversed: model.current_card populates card_pane.text. (Note: JRuby handles the Ruby/Java naming conversion, so the actual Swing method, setText, can be invoked using set_text = .)

Quite often, this form of simple mapping works fine, but sometimes, because of differences in data types or formatting or the needs of some application logic, you don't want direct data exchange. Monkeybars allows the use of intermediaries in the data exchange. A mapping can be passed a :using parameter (that is, a hash key pointing to an array) that indicates the alternative means to use when moving data from the model to the view, and from the view to the model. (Another reason for :using is to deal with situations when the value or state of a Swing component needs to be manipulated using component methods or child objects that do not fall into the general getProperty and setProperty pattern.)

For your code, we want to take a Textile-formatted string from the model and convert it to HTML before assigning it to the card_pane text property. To handle this, you'll create a to_html method. You also don't want to update the model's current_card value directly from the view. You'll have some special code for editing cards in the view, so you'll use nil in place of what would otherwise be some view-to-model method name.

The result is this map:

 map :view  => :content_pane.text, 
     :model => :current_card, :using => [:to_html, nil ]

You also want your Swing frame to present itself in a specific manner. By default, a Swing frame appears in the top left corner of the screen. For your application, you want it to show in the top right corner. You'll also give it a nice sliding effect so that it does not abruptly come and go.

Managing the Swing object

A view class has a special instance variable called @main_view_component that references its corresponding Swing class. View code interacts with Swing components through this object. To change the content of the flash-card text pane, for example, you could write:

 @main_view_component.card_pane.text = "Some new text"

However, because this kind of code is essentially the reason the view class exists, Monkeybars arranges it so that you can omit explicit use of @main_view_component and refer directly to its components:

 card_pane.text = "Some new text"

The base Monkeybars::View class uses method_missing to intercept such code, looks to see if it is a component reference, and if so it delegates the request to @main_view_component.

Method calls on the Swing class, though you need the explicit reference:

@main_view_component.width = 500

To achieve a nice sliding effect, the view class has methods that manipulate the height and position of the Swing frame, gradually expanding and contracting it so that, on each rendering cycle, it slides down from the top of the screen, then slides back up.

Handling requests from the controller

Monkeybars is designed to decouple key parts of the MVC tuple. Because the view has a direct reference to a Java Swing object, it is typically the hardest part to test. Monkeybars aims to reduce direct view interaction with the model and controller. The controller, however, is responsible for handling UI events. Inevitably, this means the controller needs to direct the view to respond. The controller, though, does not directly communicate with the view class. Instead, it uses signals.

You'll see the controller side of this shortly. In the view, you need to define signal handlers using the define_signal method. It takes a hash defining a signal name and a view method to handle that signal:

define_signal :name => :initialize,  
              :handler => :do_roll_up

Handler methods must take two arguments: the model (passed in from the controller), and a transfer object. The transfer object is a transient hash used to move data back and forth between controller and view. Your view has signals defined for the initial positioning of the UI, the slide in, slide out sequence, and two for beginning and ending card editing. Each of these signal handlers is quite short. Here's the do_roll_up method:

  def do_roll_up model, transfer
    hide
    move_to_top_right
    roll_up
  end

Nested controllers

Monkeybars controllers are typically used as singleton classes; you generally do not need multiple instances. A notable exception is the use of nested controllers, where a frame or panel has multiple subcomponents that are each instances of the same class, a topic beyond this article's scope. Basically it allows you to take a complex set of frames, panels, and components and break it down into a set of individual MVC tuples. An example might be an address book, where a top-level Swing frame renders multiple address objects, each being an instance of an address_entry MVC set.

The editing sequence is triggered through menu events. The Edit menu item toggles editing. In the view, the editing sequence means setting card_pane.editable = true, then swapping out the HTML-rendered content with the raw Textile card text. You also need to change the component's content type so it correctly renders plain text.

When editing is complete, the reverse is done. The pane is given HTML, and editable is set to false. The view is concerned only with managing the Swing component's state; the controller handles instructing the model to perform the text updating and saving.

Defining the controller class

Your Swing object has some menu items, but you haven't put any code for them in the view class. That code belongs in the controller. The controller handles all UI events, such as button clicks, menu selection, and text-field changes. Monkeybars arranges it so that by default all such events coming from the Swing code are quietly swallowed. You need to define event handlers for just those things you care about. In the example application, those are menu clicks.

Event handlers take this form:

    def your_component_name_action_performed
      # code
    end

(You can also define the handler to take the actual Swing event as a parameter should you want your code to use it.)

To handle the Quit menu item, you just need to exit:

  def quit_menu_item_action_performed
    java.lang.System.exit(0)
  end   

The Edit menu action needs a bit more:

  def edit_menu_item_action_performed
    if @editing
      @editing = false
      signal :end_edit
      update_card 
    else
      @editing = true
      signal :begin_edit
      update_model view_model, :current_card
    end
  end   

The code handles the toggling of editing modes, using signals to drive the view. The key thing to note is how card text is moved using the controller's model instance (implicitly passed to the view by way of the signal), and the view's copy of the model, provided by the view_model method.

Whenever a controller needs the current state of the user interface, it can use the view_state method to reference the view's copy of the model and the current transfer object. Because grabbing the model copy from view_state is so common, Monkeybars provides the view_model method.

Your controller also has a method to kick off the initial rendering, and another that handles the show/hide display sequence. Both use signals to defer the actual presentation code to the view.


Orchestrating the application

In addition to one or more MVC tuples, a Monkeybars application uses two key helper files to prepare and run your code.

Both are in the src/ directory. The manifest.rb file sets up library load paths and allows you to define which files are to be included based on whether the program is run straight from the file system or from a JAR file.

Earlier, you added redcloth.rb to lib/ruby/. In order for your application to locate this file, you need to add that directory to the load path. The same goes for the lib/java/ directory. So, make sure that manifest.rb includes these lines:

 add_to_load_path "../lib/java"
 add_to_load_path "../lib/ruby"

Also in src/ is main.rb. This is the Ruby entry point for the application. Among other things, it defines a global error handler, and it is where you would place any platform-specific code to run before executing main application logic.

The example program uses a simple loop:

begin
  flash_card = FlashController.instance
  flash_card.init_view :flash_interval_seconds => 8,
                       :show_for_seconds => 20,
                       :window_height => 200,
                       :data_src => 'data/cards.rc'

  while true do
    flash_card.present 
  end

rescue => e
  show_error_dialog_and_exit(e)
end


Executing the code

Some caveats about the generated JAR file

The JAR file created by rawr:jar does not contain everything needed to execute the program. In particular, any JARs containing libraries needed for the program (such as jruby-complete.jar and monkeybars-0.6.4.jar) are not bundled in monkey_see.jar.

When rawr:jar runs, it creates a set of files under package/deploy/. These are the files needed to execute the application, and they must be distributed together. The build_configuration.yaml file allows you to steer which files are placed in the JAR, and which files and directories are copied to the deployment directory. The data/cards.rc file, for example, could be bundled into monkey_see.jar, but because the application allows editing, it should be left as an external file so that changes can be written back.

With the code in place and a suitable data file, you can run the program. Use a rawr rake task to create an executable JAR file. When you ran rawr install at the start of the project, it created a Main.java file under src/org/rubyforge/rawr/. Running the program from a JAR requires a Main Java class; rawr generates this file, which contains basic code that looks for and interprets a main.rb file. (Or, if one is not found, it invents one in-line and uses that instead.)

The rake rawr:jar task compiles this code and packages up your files into a JAR. The build_configuration.yaml file coordinates this. Before you create the JAR, edit this file to reflect the details of the application.

To kick off your program, first build the JAR file:

$ rake rawr:jar

Then invoke it:

$ java -jar package/deploy/monkey_see.jar

You should see the flash-card screen roll down from the top right corner, stay for a bit, then roll back up.

When the window is visible, you can use the menu items to edit the currently displayed card. To quit, use the Quit menu item (Alt+Q, if you've added the accelerator key).


Conclusion

The development of JRuby as a robust, viable alternative to the traditional C implementation of Ruby means that Ruby GUI toolkits can move beyond C-based options and use UI tools available to the Java platform. Because Swing is a standard part of a Java runtime installation, Swing components give (J)Ruby a mature and readily available graphical toolkit. Using the Java platform means that such applications can be readily built, packaged, and distributed to users on multiple platforms. By using the Monkeybars library, Ruby developers can build testable, maintainable, and complex desktop applications with increased ease.

This article's example was deliberately small, intended mainly as an introduction to what is possible for JRuby Swing GUI development. You can find more information and larger examples at the Monkeybars site (see Resources).



Download

DescriptionNameSizeDownload method
Sample code for this articlej-monkeybars.zip25KBHTTP

Information about download methods


Resources

Learn

Get products and technologies

  • JRuby: Download jruby-complete.jar.

  • Monkeybars: Download the current Monkeybars source code.

Discuss

About the author

James Britt

James Britt is a principal at Happy Camper Studios, a Ruby application development company in Phoenix, Arizona. An active voice in the Ruby community, James has presented at Ruby conferences in the United States and Europe and written numerous technical articles for publications such as Dr. Dobbs and Linux Journal. He wrote most of the Web development section in Hal Fulton's book, The Ruby Way, 2nd ed. James also created and maintains Ruby-doc.org, the main documentation site for the Ruby language.

Comments



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology, Open source
ArticleID=343669
ArticleTitle=Cross-platform development with JRuby and Swing
publish-date=10072008
author1-email=james@happycamperstudios.com
author1-email-cc=jaloi@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers