Sun Java Solaris Communities My SDN Account Join SDN
 
Swing Introduction

Swing

 

Bookshelf Index


Introduction | Download Chapter 18| Download Chapter 22
<< NEXT >>

Class ColumnData

This class encapsulates data describing the visual characteristics of a single TableColumn of our table. The instance variables defined in this class have the following meaning:

  • String m_title: column title


  • int m_width: column width in pixels


  • int m_alignment: text alignment as defined in JLabel
  • The only constructor provided assigns each of these variables the data passed as parameters.

    Class StockTableData

    This class extends AbstractTableModel to serve as the data model for our table. Recall that AbstractTableModel is an abstract class, and three methods must be implemented to instantiate it:

  • public int getRowCount(): returns the number of rows in the table.


  • public int getColumnCount(): returns the number of columns in the table.


  • public Object getValueAt(int row, int column): returns data in the specified cell as an Object instance.
  • Note: An alternative approach is to extend the DefaultTableModel class which is a concrete implementation of AbstractTableModel. However, this is not recommended, as the few abstract methods in AbstractTableModel can be easily implemented. Usage of DefaultTableModel often creates unnecessary overhead.

    By design, this class manages all information about our table, including the title and column data. A static array of ColumnData, m_columns, is provided to hold information about our table's columns (it is used in the StocksTable constructor, see above). Three instance variables have the following meaning:

  • SimpleDateFormat m_frm: used to format dates


  • Date m_date: date of currently stored market data


  • Vector m_vector: collection of StockData instances for each row in the table
  • The only constructor of the StockTableData class initializes two of these variables and calls the setDefaultData() method to assign the pre-defined default data to m_date and m_vector (in a later example we'll see how to use JDBC to retrieve data from a database rather than using hard-coded data as we do here).

    As we discussed above, the getRowCount() and getColumnCount() methods should return the number of rows and columns, respectively. So their implementation is fairly obvious. The only catch is that they may be called by the AbstractTableModel constructor before any member variable is initialized. So we have to check for a null instance of m_vector. Note that m_columns, as a static variable, will be initialized before any non-static code is executed (so we don't have to check m_columns against null).

    The remainder of the StockTableData class implements the following methods:

  • getColumnName(): returns the column title.


  • isCellEditable(): always returns false, because we want to disable all editing.


  • getValueAt(): retrieves data for a given cell as an Object. Depending on the column index, one of the StockData fields is returned.


  • getTitle(): returns our table's title as a String to be used in a JLabel in the northern region of our frame's content pane.
  • Running the Code

    Figure 18.1 shows StocksTable in action displaying our hard-coded stock data. Note that the TableColumns resize properly in response to the parent frame size. Also note that the selected row in our table can be moved by changed with the mouse or arrow keys, but no editing is allowed.

    18.3 Stocks Table: Part II - Custom Renderers

    Now we'll extend StocksTable to use color and small icons in rendering our table cells. To enhance data visibility, we'll make the following two enhancements:

  • Render absolute and percent changes in green for positive values and red for negative values.


  • Add an icon next to each stock symbol: arrow up for positive changes and arrow down for negative.
  • To do this we need to build our own custom TreeCellRenderer.

    Figure 18.2 JTable using a custom cell renderer.

    The Code: StocksTable.java see \Chapter18\2
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import java.io.*;
    import java.text.*;
    
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    import javax.swing.table.*;
    
    public class StocksTable 
                   extends JFrame 
    {
      // Unchanged code from 
      //section 18.2
    
      public StocksTable() {
        // Unchanged code from 
        //section 18.2
            
        for (int k = 0; k < 
          StockTableData.m_columns.length; 
                                    k++) {
          DefaultTableCellRenderer 
                       renderer = new 
            ColoredTableCellRenderer();
          renderer.setHorizontalAlignment(
            StockTableData.m_columns[
                          k].m_alignment);
          TableColumn column = 
                        new TableColumn(k, 
            StockTableData.m_columns[
              k].m_width, renderer, null);
          m_table.addColumn(column);   
        }
    
        // Unchanged code from 
        //section 18.2
      }
    
      public static void main(String argv[]) {
        new StocksTable();
      }
    }
    
    class ColoredTableCellRenderer 
          extends DefaultTableCellRenderer
    {
      public void setValue(Object value) {
        if (value instanceof ColorData) {
          ColorData cvalue = (ColorData)value;
          setForeground(cvalue.m_color);
          setText(cvalue.m_data.toString());
        }
        else if (value instanceof IconData) {
          IconData ivalue = (IconData)value;
          setIcon(ivalue.m_icon);
          setText(ivalue.m_data.toString());
        }
        else
          super.setValue(value);
      }
    }
    
    class ColorData
    {
      public Color  m_color;
      public Object m_data;
      public static Color GREEN = 
                         new Color(0, 128, 0);
      public static Color RED = 
                             Color.red;
    
      public ColorData(
           Color color, Object data) {
        m_color = color;
        m_data  = data;
      }
        
      public ColorData(Double data) {
        m_color = data.doubleValue() 
                >= 0 ? GREEN : RED;
        m_data  = data;
      }
        
      public String toString() {
        return m_data.toString();
      }
    }
    
    class IconData
    {
      public ImageIcon  m_icon;
      public Object m_data;
    
      public IconData(
         ImageIcon icon, Object data) {
        m_icon = icon;
        m_data = data;
      }
        
      public String toString() {
        return m_data.toString();
      }
    }
    
    class StockData
    {
      public static ImageIcon ICON_UP = 
                 new ImageIcon("ArrUp.gif");
      public static ImageIcon ICON_DOWN = 
               new ImageIcon("ArrDown.gif");
      public static ImageIcon ICON_BLANK = 
                 new ImageIcon("blank.gif");
    
      public IconData  m_symbol;
      public String  m_name;
      public Double  m_last;
      public Double  m_open;
      public ColorData  m_change;
      public ColorData  m_changePr;
      public Long    m_volume;
    
      public StockData(
            String symbol, String name, 
                             double last, 
       double open, double change, double 
                 changePr, long volume) {
        m_symbol = 
          new IconData(getIcon(
                         change), symbol);
        m_name = name;
        m_last = new Double(last);
        m_open = new Double(open);
        m_change = new ColorData(
                     new Double(change));
        m_changePr = new ColorData(
                   new Double(changePr));
        m_volume = new Long(volume);
      }
    
      public static ImageIcon 
                getIcon(double change) {
        return (change>0 ? ICON_UP : 
              (change<0 ? ICON_DOWN : 
          ICON_BLANK));
      }
    }
    
    // Class StockTableData unchanged 
    //from section 18.2
    
    

    Understanding the Code

    Class StocksTable The only change we need to make in the base frame class is to change the column renderer to a new class, ColoredTableCellRenderer. ColoredTableCellRenderer should be able to draw icons and colored text, but not both at the same time---although this could be done using this same approach.

    Class ColoredTableCellRenderer

    This class extends DefaultTableCellRenderer and overrides only one method: setValue(). This method will be called prior to the rendering of a cell to retrieve its corresponding data (of any nature) as an Object. Our overridden setValue() method is able to recognize two specific kinds of cell data: ColorData, which adds color to a data object, and IconData, which adds an icon (both are described below). If a ColorData instance is detected, its encapsulated color is set as the foreground for the renderer. If an IconData instance is detected, its encapsulated icon is assigned to the renderer with the setIcon() method (which is inherited from JLabel). If the value is neither a ColorData or an IconData instance we call the super-class setValue() method.

    Class ColorData

    This class is used to bind a specific color, m_color, to a data object of any nature, m_data. Two static ColorsRED and GREEN, are declared to avoid creation of numerous temporary objects. Two constructors are provided for this class. The first constructor takes Color and Object parameters and assigns them to instance variables m_color and m_data respectively. The second constructor takes a Double parameter which gets assigned to m_data, and m_color is assigned the green color if the parameter is positive, and red if negative. The toString() method simply calls the toString() method of the data object.

    Class IconData

    This class is used to bind ImageIcon m_icon to a data object of any nature, m_data. Its only constructor takes ImageIcon and Object parameters. The toString() method simply calls the toString() method of the data object.

    Class StockData

    This class has been enhanced from its previous version to to provide images and new variable data types. We've prepared three static ImageIcon instances holding images: arrow up, arrow down, and a blank, all transparent image. The static getIcon() method returns one of these images depending on the sign of the given double parameter. We've also changed three instance variables to bind data with the color and image attributes according to the following table:

    FieldNew typeData object Description
    m_symbolIconDataStringStock's symbol (NYSE or NASDAQ)
    m_changeColorData DoubleAbsolute change in price
    m_changePrColorDataDoublePercent change in price

    The corresponding changes are also required in the StockData constructor.

    Page 1 2 3 4 5 6 7 8 9 10 11

    << NEXT >>
    Download Chapter 18| Download Chapter 22]