Software documentation

Development tools

Code Structure

Techniques and Standards

How To

Functional Info

Background Info

JMRI: Use of Swing

(Note: This page describes a toolkit to for creating JMRI's GUI that's been slowly developed as part of JMRI. Please use this if you're creating new JMRI user interfaces. Note that there are proposals to move JMRI to other, non-specific toolkits in this area. Before you do work to extend or improve this toolkit itself, please ask on jmri-developers about that status of that work.)

We use Java Swing for our GUI development. It's a lot more powerful than the original AWT, and the price is right. In particular, we try to use the "Bean format" of setting and getting members, call-backs to notify of changes, etc, to make it easier to build applications from JMRI components.

We have been evolving a particular pattern for using Swing, described here. The JMRI codebase contains several generations of implementations, so not all of it looks like this, but we're moving classes in this direction as time allows.

The basic structure is

The jmri.util.swing package contains the support code.

Life Cycle of a JmriPanel

First the ctor runs, then initComponents. That second part should be the place for connections to other components, as all lower level objects have been created. (subclasses for particular systems might have e.g. more initComponents methods, called later)

Dispose is called at the end. (Note that JPanels don't have a dispose(), that's normally only part of JFrames, but we provide it here for cleanup)

Displaying a JmriPanel

JmriPanels are best created by name with JmriNamedPaneAction, which has the advantage of greatly reducing the number of classes that need to be loaded to populate a menu.

To create an action, e.g. for a menu item, the simplest form is:


      new jmri.util.swing.JmriNamedPaneAction("Log4J Tree", "jmri.jmrit.log.Log4JTreePane");
      
The first argument is the human-readable name, and the 2nd is the name of the panel class.

An example of a fuller form:


      new jmri.util.swing.JmriNamedPaneAction(Bundle.getMessage("MenuItemLogTreeAction"),
                new jmri.util.swing.sdi.JmriJFrameInterface(),
                "jmri.jmrit.log.Log4JTreePane");
      
See the JmriNamedPaneAction Javadoc for more information.

If you need specialized initialization that can't be built into the JmriPanel itself via it's initComponents and initContext(..) methods, perhaps to make decision about connections, make a specialized Action class by extending jmri.util.swing.JmriNamedPaneAction, providing the appropriate constructors, and including a @Override public JmriPanel makePanel() method that does any case-specific initialization that's needed before the panel can be used. For an example (may have been changed) see jmri.jmrix.loconet.swing.LnNamedPaneAction.

If none that can be used, look into using JmriAbstractAction as the base for a separate class implementing Action.

Menus, ToolsBars, Buttons, etc

If you're using JmriPanels as described above, JMRI also provides tools for creating menus, toolbars, button fields, etc more easily.

Generic creation of menus, toolbars and navigation trees from XML definition files are provided by the jmri.util.swing.JMenuUtil, jmri.util.swing.JToolBarUtil, and jmri.util.swing.JTreeUtil classes

I18N of those menus, toolbars and trees is then done via the XML content in the usual way.

Window Control

JMRI provides three different ways of embedding JmriPanels in windows:
  • The jmri.util.swing.sdi package provides the traditional JMRI "single-document interface", where there are multiple independent windows
  • jThe mri.util.swing.multipane package provides a "multi-pane" or IDE-style interface", where each window is tiled with inter-related panes. This is used for the (new) DecoderPro.
  • The jmri.util.swing.mdi package provides a "multi-document interface", where a primary window contains multiple independent sub-windows. This currently isn't used by a JMRI app, at least not as far as we know, but it's available if wanted.

Each of those then provides an implementation of WindowInterface that creates new windows, subwindows or other constructs as needed, so as to put panels in the right place.

(See the jmri.util.swing package Javadocs for more information

Misc

(This section needs more organization)

JmriJFrame is in the wrong package for historical reasons, will eventually move to jmri.util.swing.

Older classes, some still to be moved to jmri.util.swing, some are 1.1.8 adapters that should just go away.

AbstractFrameAction
BusyGlassPane
FileChooserFilter
FontUtil
JTableUtil
JmriInsets
JmriJFrame
JmriJFrameAction
JmriSpinner
MouseInputAdapterInstaller
ResizableImagePanel
WindowMenu