The Source for Java Technology Collaboration


Home | Changes | Index | Search | Go

SwingLabs: How to Use the SwingX JXTable

A JXTable is an extension to the standard Swing JTable adding support for runtime column selection, background row highlighting, sorting and other features. A JXTable can be used just like a JTable, while allowing you to offer your users an extended feature set with no extra coding.

The extended features of JXTable are:

Feature What it does
Column Control The JXTable introduces a small column control button, which opens a popup menu to configure the JXTable's display and behavior. The column control appears discretely to the right of the column headers.
Selecting Columns Users can select the columns they want to see on the JXTable by selecting the columns from the column control's popup menu; this can also be done programmatically.
Highlighting Rows You can highlight rows in a JXTable by attaching a Highlighter. Highlighting allows you to easily distinguish between different rows, for example, every other row, using a subtle background color scheme.
Sorting Rows JXTable has built-in support for row sorting at runtime, allowing the user to click on a column header and sort by that column. Using custom Comparators, you can determine the sorting rules that apply to different columns.
Filtering Rows You can attach one or more filters to a JXTable, allowing you to control which rows are shown to the user.
Resizing Columns Users can auto-resize columns to fit their contents from the column control.
Horizontal Scroll Control With a single command, you can request that the table auto-resize to fit the viewport it's in, or to allow columns to scroll off to the right.

Contents of this How-To

Working with a JXTable

This section covers how to use a JXTable in your code. We start with an overview of using a JXTable, then continue by describing each major feature of JXTable in turn.

Sample Code

This How-To is based on a single sample program, org.jdesktop.demo.sample.SampleJXTableDemo in the SwingLabs-Demos subproject. Code samples shown here are taken from that class.

SampleJXTableDemo can be run directly from the command line as long as you have the SwingX distribution jar in your classpath.

Getting Started with a JXTable

JXTable is a JTable subclass, and is instantiated in the same way--you need to provide a TableModel to use it, and wrap it in a JScrollPane so that headers show up.

From SampleJXTableDemo:

    private JXTable initTable() {
        // boilerplate table-setup; this would be the similar for a JTable
        // boilerplate table-setup; this would be the same for a JTable
        JXTable table = new JXTable();
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        // if we would want a per-table ColumnFactory we would have
        // to set it here, before setting the model
        // table.setColumnFactory(myVerySpecialColumnFactory);
        SampleTableModel model = new SampleTableModel();
        table.setModel(model);
        model.loadData();
        return table;
    }

We won't show the SampleTableModel here--it's just an inner class subclassing DefaultTableModel that loads data from a text file. What's important is that we are just using a TableModel (or DefaultTableModel), and adding rows and columns just as we would with JTable.

Once we've initialized our JXTable, we can add it to a JScrollPane and we're ready to use it.

The JXTable Column Control

The JXTable Column Control is an icon that renders to the right of the column headers, just above the vertical scrollbar. When a user clicks the icon, a popup menu appears, allowing the user to show or hide columns from the view, and to set a couple of other properties.

The Column Control is available automatically as part of =JXTable=--that is, all you need to do is call

        // All there is to it--users can now select which columns to view
        jxTable.setColumnControlVisible(true);

And it shows up. Apart from showing and hiding columns, users can also change the horizontal scroll policy, and request that columns be resized (packed). Horizontal scrolling and column packing are described below.

Selecting Columns at Runtime

As we noted above, the column control on the table header allows users to show and hide columns in the table. The selection of columns is the set of all columns assigned to the TableModel. A column can be shown or hidden through the column control, as well as programmatically. In the SampleJXTableDemo, we hide some columns manually because our data source is too wide.

        TableColumnExt latitude = jxTable.getColumnExt("LATITUDE");
        latitude.setVisible(false);

        jxTable.getColumnExt("LONGITUDE").setVisible(false);

This sample code shows a long and a short way to do this. Visibility is a property of a TableColumnExt, a class which extends TableColumn. TableColumn itself doesn't know about visibility, whereas TableColumnExt allows a column to negotiate visibility with its owning table. Although you create a JXTable using a TableModel which contains TableColumns, a JXTable internally uses a TableColumnExt for each column. To get a reference to the TableColumnExt, you can use one of the accessor methods-- getColumnExt(Object identifier) and getColumnExt(int viewColumnIndex). Once we have the TableColumnExt for a column, we simply use the setVisible(boolean showIt) method to show or hide the column. The Column Control uses this visibility mechanism in the background.

Highlighting Rows

JXTable supports a highlighting mechanism which changes the background color of rows. With JTable, you would need to supply your own renderer to do this; with JXTable, you supply one or more Highlighters. A Highlighter implements rules for how a cell's visual properties should be changed.

In the SampleJXTableDemo, we ask the HighlighterFactory to create a background striping Highlighter with the color provided by the current LookAndFeel?

    jxTable.setHighlighters(HighlighterFactory.createSimpleStriping());

An striping highlighter changes the color of every other row in the table. The CLASSIC_LINE_PRINTER mimics the color scheme on old printer paper where every other line was colored a light green, to improve legibility.

A JXTable can have one or more Highlighters assigned. You can also add and remove Highlighters programmatically using addHighlighter() and removeHighlighter(). When more than one Highlighter is assigned, each one is called in turn to apply its highlighting.

In the SampleJXTable demo, we add a second highlighter after the fact:

  // oops .. forgot one
  jxTable.addHighlighter(new ColorHighlighter(Color.CYAN, Color.WHITE,
                HighlightPredicate.ROLLOVER_ROW));

A HighlightPredicate is a rule which a Highlighter asks when doing the hightlight on every cell painting: only applies the highlight effect if the condition is true. A ROLLOVER_ROW is true if the mouse location is somewhere over the row to paint. JXTable has the rollover support enabled by default.

Sorting Rows

With JTable, programmers had to wrap the table in a TableSorter or other mechanism to provide automatic row sorting. JXTable has built-in support for sorting by column: users can sort any column by clicking on it. The column will sort alternately in ascending or descending order each time a given column is clicked.

JXTables have column sorting turned on by default. You can disable all column sorting using setSortingEnabled(boolean allowSort). You can also disable sorting on a single column by using =setSortable(boolean sortable).

The default sorter used on a column can be overridden by supplying a new Comparator for the sorting algorithm. A good example of this is in the SwingXDemo, where a point (x, y) is sorted on the value of x and y as a Point, and not as a String. In the SimpleJXTableDemo, we create a special sorter for our columns with float values, to have the column sort in proper numeric order.

        Comparator numberComparator = new Comparator() {
            public int compare(Object o1, Object o2) {
                Double d1 = Double.valueOf(o1 == null ? "0" : (String)o1);
                Double d2 = Double.valueOf(o2 == null ? "0" : (String)o2);
                return d1.compareTo(d2);
            }
        };
        jxTable.getColumnExt("ELEVATION").setComparator(numberComparator);
        jxTable.getColumnExt("TEMPERATURE").setComparator(numberComparator);

Filtering Rows from Display

You can remove rows from a JXTable without modifying the underlying model by using Filters. Like Highlighters, Filters can be chained together in a pipeline, the FilterPipeline, and are added to a table using setFilters(FilterPipeline? pipeline).

In the SampleJXTableDemo, we use a filter to only show rows for countries who's names begin with A using a Pattern filter against the country column.

        int col = jxTable.getColumn("COUNTRY").getModelIndex();
        jxTable.setFilters(new FilterPipeline(new PatternFilter("^A", 0, col)));

Filters don't actually remove or delete data from the TableModel; they just hide it (or, in the case of a Sorter, cause row order to appear different than the underlying model). Removing a PatternFilter, for example, will cause all rows that were previously hidden to be displayed.

Resizing Columns

JXTable supports several convenience methods for resizing column width. From the Column Control, to resize all columns to fit within the current viewport, select Pack All Columns. Programmatically, you can do this using the packAll(), packColumn(int col, int margin, int max), packSelected() and packTable(int margin) methods.

Packing will have a different effect if horizontal scrolling is enabled. With horizontal scrolling, the JXTable allows the table to scroll off to the right of the viewport, so the resize algorithm doesn't need to try and fit all columns within the more constrained viewport area. If you turn horizontal scrolling on, and pack all columns, you'll see them all get adjusted to their preferred width.

We should mention that the TableColumnExt also allows you to set prototype values. A prototype value for a column is a sample String that indicates the maximum length for a value in that column. Normally, when a column is resized, the JTable has to guess at the widest column value, as in large tables it couldn't actually check all values in the column. With the prototype value, you can hint to the table the size of data that will be in that column, allowing it to resize more accurately for the data set.

Horizontal Scrolling

As described above, normally a JXTable nestled in a JScrollPane will fit all columns within the scroll pane's viewport, possibly causing some of them to resize beneath an optimal width and making them illegible. You can use setHorizontalScrolling(boolean allowHoriz) with a value of true in order for the scroll pane to allow a horizontal scrollbar, with the end result that columns are resized to their preferred width.

Links to Demos and Related Documents

TODO: SwingXDemo, other demos? TODO: related classes: JXTreeTable, JXScrollPane?, Filter?, Highlighter?

Topic SwingLabsSwingXJXTableHowTo . { Edit | Ref-By | Printable | Diffs r4 < r3 < r2 < r1 | More }
 XML java.net RSS

Revision r4 - 23 Feb 2008 - 12:46:29 - Main.christoph_pickl
Parents: WebHome > SwingLabs > SwingLabsSwingX
Javadesktop.SwingLabsSwingXJXTableHowTo moved from Javadesktop.JDNCJXTableHowTo on 15 Sep 2005 - 10:57 by PatrickWright - put it back