Putting a Image on a JButton

Check out the API! You’ll see that there is a constructor taking an Icon object as parameter. Here’s an example showing two buttons with the following animated gifs on them:

Main.java:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
  
public class Main extends JFrame implements ActionListener {
   JList list; 
 
   public Main() {
      getContentPane().setLayout(new FlowLayout());
 
      JButton mbutton = new JButton("female", new ImageIcon("male.gif"));
      JButton fbutton = new JButton("male", new ImageIcon("female.gif"));
      mbutton.addActionListener(this);
      fbutton.addActionListener(this);
      getContentPane().add(mbutton);
      getContentPane().add(fbutton);
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      pack();
   }
 
   public void actionPerformed(ActionEvent ae) {
      System.out.println("Your pressed the " + ae.getActionCommand() + " button");
   }
   
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Dynamically changing the font size of a JComboBox

Main.java:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      Vector v = new Vector();
      for (int i=10; i<100; i+=5) {
         v.addElement(""+i);
      }
 
      final JComboBox combobox = new JComboBox(v);
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
      getContentPane().add(new JLabel("Select font size:"));
      getContentPane().add(combobox);
 
      Font f = combobox.getFont();
      combobox.setFont(f.deriveFont(10.0f));
  
      combobox.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            Font f = combobox.getFont();
            combobox.setFont(f.deriveFont(
                                new Float(""+combobox.getSelectedItem()).
                                          floatValue()));
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(200, 200);
      main.setVisible(true);
   }
}

Adding a border to each element in a JList

Change the default cell renderer as in following example:

import javax.swing.border.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
 
public class Main {
   public static void main(String args[]) {
      JFrame frame = new JFrame("JList Background Demonstration");
      final ImageIcon imageIcon = new ImageIcon("bg1.jpg");
 
      Vector v = new Vector();
      for (int i=0; i<10; i++) {
         v.addElement("Item #" + i);
      }
 
      JList list = new JList(v);
 
      list.setCellRenderer(new BorderCellRenderer(new BevelBorder(BevelBorder.LOWERED)));
//      list.setCellRenderer(new BorderCellRenderer(new BevelBorder(BevelBorder.RAISED)));
//      list.setCellRenderer(new BorderCellRenderer(new EtchedBorder(EtchedBorder.LOWERED)));
//      list.setCellRenderer(new BorderCellRenderer(new EtchedBorder(EtchedBorder.RAISED)));
      
      frame.getContentPane().add(BorderLayout.CENTER, list); //new JScrollPane(list));
      frame.setDefaultCloseOperation(3);
      frame.pack();
      frame.setVisible(true);
   }
}
 
class BorderCellRenderer extends DefaultListCellRenderer implements ListCellRenderer {
   AbstractBorder border;
 
   public BorderCellRenderer(AbstractBorder border) {
      this.border = border;
   }
 
   public Component getListCellRendererComponent(
      JList list,
      Object value,            // value to display
      int index,               // cell index
      boolean isSelected,      // is the cell selected
      boolean cellHasFocus)    // the list and the cell have the focus
   {
      Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
 
      ((JComponent) c).setBorder(border);
 
      return c;
   }
}

Changing the colors of my JMenu and JMenuItems

Use setForeground and setBackground. You can change the default selection colors using the UIManager.

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
    
public class Main extends JFrame {
   public Main() {
      getContentPane().setLayout(new FlowLayout());
  
      // change default selection colors
      UIManager.put("Menu.selectionBackground", 
             new javax.swing.plaf.ColorUIResource(Color.blue));
      UIManager.put("MenuItem.selectionBackground", 
             new javax.swing.plaf.ColorUIResource(Color.green));
 
      JMenuBar menuBar = new JMenuBar();
      JMenu menu = new JMenu("Sex");
      JMenuItem menuItem1 = new JMenuItem("male");
      JMenuItem menuItem2 = new JMenuItem("female");
      JMenuItem menuItem3 = new JMenuItem("androgyne");
 
      menuItem1.setBackground(Color.red);
      menuItem1.setForeground(Color.yellow);
      menuItem2.setBackground(Color.red);
      menuItem2.setForeground(Color.yellow);
      menuItem3.setBackground(Color.red);
      menuItem3.setForeground(Color.yellow);
  
      menu.setBackground(Color.white);
      menu.setForeground(Color.blue);
 
      // add the MenuItems to the Menu 
      menu.add(menuItem1);
      menu.add(menuItem2);
      menu.add(menuItem3);
  
      menuBar.add(menu);
  
      this.setJMenuBar(menuBar); 
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
  
      setSize(400, 400);
   }
  
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Creating a JFormattedTextField that only accepts telephone numbers

Main.java:

import javax.swing.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.*;
import java.awt.*;
 
public class Main extends JFrame 
{
   public Main() throws Exception
   {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      final JFormattedTextField formattedTf =
                   new JFormattedTextField(new MaskFormatter("(###) ###-####"));
 
      final JTextField normalTf = new JTextField(25);
      JButton button = new JButton("Get value");
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) { 
            normalTf.setText(""+formattedTf.getValue());
         }
      });
 
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
      getContentPane().add(formattedTf);
      getContentPane().add(button);
      getContentPane().add(normalTf);
 
      formattedTf.setPreferredSize(normalTf.getPreferredSize());
   }
  
   public static void main(String args[]) throws Exception 
   {
      Main main = new Main();
      main.setSize(300, 150);
      main.setVisible(true);
   }
}

Creating an editable JLabel

You can use a CardLayout, assign card 1 a JLabel and assign card 2 a JTextField. Show card 1 and switch to card 2 when it is time to edit. In the following example, the behavior is defined to edit the JLabel whenever the mouse moves over it.

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.text.*;
import java.awt.*;
   
public class Main extends JFrame {
   public Main() {
      getContentPane().setLayout(new FlowLayout());
 
      final JLabel label = new JLabel("Move your mouse over this JLabel!");
      final JTextField textfield = new JTextField();
 
      final CardLayout cl = new CardLayout();
      final JPanel panel = new JPanel(cl);
 
      panel.add(label, "label component");
      panel.add(textfield, "textfield component");
 
      getContentPane().add(panel);
  
      label.addMouseListener(new MouseAdapter() {
         public final void mouseEntered(MouseEvent evt) { 
            textfield.setText(label.getText());
            cl.show(panel, "textfield component");
         } 
      });
 
      textfield.addMouseListener(new MouseAdapter() {
         public final void mouseExited(MouseEvent evt) { 
            label.setText(textfield.getText());
            cl.show(panel, "label component");
         } 
      }); 
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      setSize(300, 200);
   }
 
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Allowing only individual rows to be selected in a JTable

By default, multiple rows can be selected in a Table. You can change this behavior through a ListSelectionModel. Invoke the method setSelectionMode on your JTable object and set it to one of these three static final variables defined in ListSelectionModel:

MULTIPLE_INTERVAL_SELECTION: to allow multiple contiguous selection ranges
SINGLE_INTERVAL_SELECTION: to allow one contiguous selection range
SINGLE_SELECTION: to allow only one list index selection

Add a ListSelectionListener and define the behaviour in valueChanged.

Here’s a working example:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame 
{
   public Main() {
      super("Table example, Wines from Bordeaux");
 
      Object[][] tabledata = {
            { "Chateau Meyney, St. Estephe", 	   new Integer(1994), "$18.75"},
            { "Chateau Montrose, St. Estephe", 	   new Integer(1975), "$54.25" },
            { "Chateau Gloria, St. Julien", 	   new Integer(1993), "$22.99" },
            { "Chateau Beychevelle, St. Julien",   new Integer(1970), "$61.63" },
            { "Chateau La Tour de Mons, Margeaux", new Integer(1975), "$57.03" },
            { "Chateau Brane-Cantenac, Margeaux",  new Integer(1978), "$49.92" },
      };
 
      String columnheaders[] = { "Wine", "Vintage", "Price" };
 
      JTable table = new JTable(tabledata, columnheaders);
      table.setPreferredScrollableViewportSize(new Dimension(500, 70));
      JScrollPane scrollPane = new JScrollPane(table);
 
      table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      ListSelectionModel listSelectionModel = table.getSelectionModel();
      listSelectionModel.addListSelectionListener(new ListSelectionListener() {
         public void valueChanged(ListSelectionEvent e) {
 
            // ignore clicks when user is still making his selection,
            // eg. dragging the mouse
            if (e.getValueIsAdjusting()) return;
                  
            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
            if (lsm.isSelectionEmpty()) {
               System.out.println("No selection!");
            } else {
               int selectedRow = lsm.getMinSelectionIndex();
               System.out.println("Row selected: " + selectedRow);
            }
 
         } 
      });
  
      getContentPane().add(scrollPane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      pack();
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
}

Creating a JTable with multiple row headers

Courtesy of Nobuo Tamemasa (http://www2.gol.com/users/tame/swing/examples/JTableExamples1.htm7)



MultipleRowHeaderExample.java:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
   
/*   ----------------------------------------------
 *  |         SNo.        |
 *   ----------------------------------------------
 *  |          |     1    |
 *  |   Name   |-----------------------------------
 *  |          |     2    |
 *   ----------------------------------------------
 *  |          |     1    |
 *  |          |-----------------------------------
 *  | Language |     2    |
 *  |          |-----------------------------------
 *  |          |     3    |
 *   ----------------------------------------------
 */
 
/**
 * @version 1.0 03/06/99
 */
public class MultipleRowHeaderExample extends JFrame {
  Object[][] data;
  Object[] column;
  JTable table;
  MultiSpanCellTable fixedTable;
 
  public MultipleRowHeaderExample() {
    super( "Multiple Row Header Example" );
    setSize( 400, 150 );
    
    data =  new Object[][]{
        {"SNo."    ,"" },
        {"Name"    ,"1"},
        {""        ,"2"},
        {"Language","1"},
        {""        ,"2"},
        {""        ,"3"}};
    column = new Object[]{"",""};
    
    AttributiveCellTableModel fixedModel = new AttributiveCellTableModel(data, column) {
      public boolean CellEditable(int row, int col) { 
        return false; 
      }
    };
        
    CellSpan cellAtt =(CellSpan)fixedModel.getCellAttribute();
    cellAtt.combine(new int[] {0}    ,new int[] {0,1});
    cellAtt.combine(new int[] {1,2}  ,new int[] {0});
    cellAtt.combine(new int[] {3,4,5},new int[] {0});
    
    DefaultTableModel    model = new DefaultTableModel(data.length, 3);
        
    fixedTable = new MultiSpanCellTable( fixedModel );
    table = new JTable( model );
    fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    fixedTable.setDefaultRenderer(Object.class, new RowHeaderRenderer(fixedTable));
    fixedTable.setGridColor(table.getTableHeader().getBackground());
    
    JScrollPane scroll = new JScrollPane( table );
    JViewport viewport = new JViewport();
    viewport.setView(fixedTable);
    viewport.setPreferredSize(fixedTable.getPreferredSize());
    scroll.setRowHeaderView(viewport);
    
    getContentPane().add(scroll, BorderLayout.CENTER);
  }
 
  public static void main(String[] args) {
    MultipleRowHeaderExample frame = new MultipleRowHeaderExample();
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent e ) {
        System.exit(0);
      }
    });
    frame.setVisible(true);
  }
  
  class RowHeaderRenderer extends JLabel implements TableCellRenderer {  
    RowHeaderRenderer(JTable table) {
      JTableHeader header = table.getTableHeader();
      setOpaque(true);
      setBorder(UIManager.getBorder("TableHeader.cellBorder"));
      setHorizontalAlignment(CENTER);
      setForeground(header.getForeground());
      setBackground(header.getBackground());
      setFont(header.getFont());
    }
   
    public Component getTableCellRendererComponent(JTable table, Object value,
                          boolean isSelected, boolean hasFocus, int row, int column) {
      setText((value == null) ? "" : value.toString());
      return this;
    }
  }
  
}

AttributiveCellTableModel.java:

import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
 
/**
 * @version 1.0 11/22/98
 */
 
public class AttributiveCellTableModel extends DefaultTableModel {
 
  protected CellAttribute cellAtt;
     
  public AttributiveCellTableModel() {
    this((Vector)null, 0);
  }
  public AttributiveCellTableModel(int numRows, int numColumns) {
    Vector names = new Vector(numColumns);
    names.setSize(numColumns);
    setColumnIdentifiers(names);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows,numColumns);
  }
  public AttributiveCellTableModel(Vector columnNames, int numRows) {
    setColumnIdentifiers(columnNames);
    dataVector = new Vector();
    setNumRows(numRows);
    cellAtt = new DefaultCellAttribute(numRows,columnNames.size());
  }
  public AttributiveCellTableModel(Object[] columnNames, int numRows) {
    this(convertToVector(columnNames), numRows);
  }  
  public AttributiveCellTableModel(Vector data, Vector columnNames) {
    setDataVector(data, columnNames);
  }
  public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
    setDataVector(data, columnNames);
  }
     
  public void setDataVector(Vector newData, Vector columnNames) {
    if (newData == null)
      throw new IllegalArgumentException("setDataVector() - Null parameter");
    dataVector = new Vector(0);
    setColumnIdentifiers(columnNames);
    dataVector = newData;
     
    //
    cellAtt = new DefaultCellAttribute(dataVector.size(),
                                       columnIdentifiers.size());
     
    newRowsAdded(new TableModelEvent(this, 0, getRowCount()-1,
                 TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
 
  public void addColumn(Object columnName, Vector columnData) {
    if (columnName == null)
      throw new IllegalArgumentException("addColumn() - null parameter");
    columnIdentifiers.addElement(columnName);
    int index = 0;
    Enumeration enumeration = dataVector.elements();
    while (enumeration.hasMoreElements()) {
      Object value;
      if ((columnData != null) && (index < columnData.size()))
          value = columnData.elementAt(index);
      else
        value = null;
      ((Vector)enumeration.nextElement()).addElement(value);
      index++;
    }
 
    //
    cellAtt.addColumn();

    fireTableStructureChanged();
  }
 
  public void addRow(Vector rowData) {
    Vector newData = null;
    if (rowData == null) {
      newData = new Vector(getColumnCount());
    }
    else {
      rowData.setSize(getColumnCount());
    }
    dataVector.addElement(newData);
 
    //
    cellAtt.addRow();
 
    newRowsAdded(new TableModelEvent(this, getRowCount()-1, getRowCount()-1,
       TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
 
  public void insertRow(int row, Vector rowData) {
    if (rowData == null) {
      rowData = new Vector(getColumnCount());
    }
    else {
      rowData.setSize(getColumnCount());
    }
 
    dataVector.insertElementAt(rowData, row);
 
    //
    cellAtt.insertRow(row);
 
    newRowsAdded(new TableModelEvent(this, row, row,
       TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
  }
  
  public CellAttribute getCellAttribute() {
    return cellAtt;
  }
 
  public void setCellAttribute(CellAttribute newCellAtt) {
    int numColumns = getColumnCount();
    int numRows    = getRowCount();
    if ((newCellAtt.getSize().width  != numColumns) ||
        (newCellAtt.getSize().height != numRows)) {
      newCellAtt.setSize(new Dimension(numRows, numColumns));
    }
    cellAtt = newCellAtt;
    fireTableDataChanged();
  }
 
  /*
  public void changeCellAttribute(int row, int column, Object command) {
    cellAtt.changeAttribute(row, column, command);
  }
 
  public void changeCellAttribute(int[] rows, int[] columns, Object command) {
    cellAtt.changeAttribute(rows, columns, command);
  }
  */
}

DefaultCellAttribute.java:

import java.awt.*;
 
/**
 * @version 1.0 11/22/98
 */
 
public class DefaultCellAttribute 
//    implements CellAttribute ,CellSpan  {
      implements CellAttribute ,CellSpan ,ColoredCell ,CellFont {
 
  //
  // !!!! CAUTION !!!!!
  // these values must be synchronized to Table data
  //
  protected int rowSize;
  protected int columnSize;
  protected int[][][] span;                   // CellSpan
  protected Color[][] foreground;             // ColoredCell
  protected Color[][] background;             //
  protected Font[][]  font;                   // CellFont
   
  public DefaultCellAttribute() {
    this(1,1);
  }
   
  public DefaultCellAttribute(int numRows, int numColumns) {
    setSize(new Dimension(numColumns, numRows));
  }
 
  protected void initValue() {
    for(int i=0; i<span.length;i++) {
      for(int j=0; j<span[i].length; j++) {
        span[i][j][CellSpan.COLUMN] = 1;
        span[i][j][CellSpan.ROW]    = 1;
      }
    }
  }
 
 
  //
  // CellSpan
  //
  public int[] getSpan(int row, int column) {
    if (isOutOfBounds(row, column)) {
      int[] ret_code = {1,1};
      return ret_code;
    }
    return span[row][column];
  }
 
  public void setSpan(int[] span, int row, int column) {
    if (isOutOfBounds(row, column)) return;
    this.span[row][column] = span;
  }
       
  public boolean isVisible(int row, int column) {
    if (isOutOfBounds(row, column)) return false;
    if ((span[row][column][CellSpan.COLUMN] < 1)
      ||(span[row][column][CellSpan.ROW]    < 1)) return false;
    return true;
  }
 
  public void combine(int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns)) return;
    int    rowSpan  = rows.length;
    int columnSpan  = columns.length;
    int startRow    = rows[0];
    int startColumn = columns[0];
    for (int i=0;i<rowSpan;i++) {
      for (int j=0;j<columnSpan;j++) {
        if ((span[startRow +i][startColumn +j][CellSpan.COLUMN] != 1)
          ||(span[startRow +i][startColumn +j][CellSpan.ROW]    != 1)) {
          //System.out.println("can't combine");
          return ;
        }
      }
    }
    for (int i=0,ii=0;i<rowSpan;i++,ii--) {
      for (int j=0,jj=0;j<columnSpan;j++,jj--) {
        span[startRow +i][startColumn +j][CellSpan.COLUMN] = jj;
        span[startRow +i][startColumn +j][CellSpan.ROW]    = ii;
        //System.out.println("r " +ii +"  c " +jj);
      }
    }
    span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
    span[startRow][startColumn][CellSpan.ROW]    =    rowSpan;
    
  }
 
  public void split(int row, int column) {
    if (isOutOfBounds(row, column)) return;
    int columnSpan = span[row][column][CellSpan.COLUMN];
    int    rowSpan = span[row][column][CellSpan.ROW];
    for (int i=0;i<rowSpan;i++) {
      for (int j=0;j<columnSpan;j++) {
        span[row +i][column +j][CellSpan.COLUMN] = 1;
        span[row +i][column +j][CellSpan.ROW]    = 1;
      }
    }
  }
 
 
  //
  // ColoredCell
  //
  public Color getForeground(int row, int column) {
    if (isOutOfBounds(row, column)) return null;
    return foreground[row][column];
  }
  public void setForeground(Color color, int row, int column) {
    if (isOutOfBounds(row, column)) return;
    foreground[row][column] = color;
  }
  public void setForeground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns)) return;
    setValues(foreground, color, rows, columns);
  }
  public Color getBackground(int row, int column) {
    if (isOutOfBounds(row, column)) return null;
    return background[row][column];
  }
  public void setBackground(Color color, int row, int column) {
    if (isOutOfBounds(row, column)) return;
    background[row][column] = color;
  }
  public void setBackground(Color color, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns)) return;
    setValues(background, color, rows, columns);
  }
  //
 
 
  //
  // CellFont
  //
  public Font getFont(int row, int column) {
    if (isOutOfBounds(row, column)) return null;
    return font[row][column];
  }
  public void setFont(Font font, int row, int column) {
    if (isOutOfBounds(row, column)) return;
    this.font[row][column] = font;
  }
  public void setFont(Font font, int[] rows, int[] columns) {
    if (isOutOfBounds(rows, columns)) return;
    setValues(this.font, font, rows, columns);
  }
  //
 
 
  //
  // CellAttribute
  //
  public void addColumn() {
    int[][][] oldSpan = span;
    int numRows    = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows][numColumns + 1][2];
    System.arraycopy(oldSpan,0,span,0,numRows);
    for (int i=0;i<numRows;i++) {
      span[i][numColumns][CellSpan.COLUMN] = 1;
      span[i][numColumns][CellSpan.ROW]    = 1;
    }
  }
 
  public void addRow() {
    int[][][] oldSpan = span;
    int numRows    = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    System.arraycopy(oldSpan,0,span,0,numRows);
    for (int i=0;i<numColumns;i++) {
      span[numRows][i][CellSpan.COLUMN] = 1;
      span[numRows][i][CellSpan.ROW]    = 1;
    }
  }
 
  public void insertRow(int row) {
    int[][][] oldSpan = span;
    int numRows    = oldSpan.length;
    int numColumns = oldSpan[0].length;
    span = new int[numRows + 1][numColumns][2];
    if (0 < row) {
      System.arraycopy(oldSpan,0,span,0,row-1);
    }
    System.arraycopy(oldSpan,0,span,row,numRows - row);
    for (int i=0;i<numColumns;i++) {
      span[row][i][CellSpan.COLUMN] = 1;
      span[row][i][CellSpan.ROW]    = 1;
    }
  }
 
  public Dimension getSize() {
    return new Dimension(rowSize, columnSize);
  }
 
  public void setSize(Dimension size) {
    columnSize = size.width;
    rowSize    = size.height;
    span = new int[rowSize][columnSize][2];   // 2: COLUMN,ROW
    foreground = new Color[rowSize][columnSize];
    background = new Color[rowSize][columnSize];
    font = new Font[rowSize][columnSize];
    initValue();
  }
 
  /*
  public void changeAttribute(int row, int column, Object command) {
  }
 
  public void changeAttribute(int[] rows, int[] columns, Object command) {
  }
  */
 
  protected boolean isOutOfBounds(int row, int column) {
    if ((row    < 0)||(rowSize    <= row)
      ||(column < 0)||(columnSize <= column)) {
      return true;
    }
    return false;
  }
 
  protected boolean isOutOfBounds(int[] rows, int[] columns) {
    for (int i=0;i<rows.length;i++) {
      if ((rows[i] < 0)||(rowSize <= rows[i])) return true;
    }
    for (int i=0;i<columns.length;i++) {
      if ((columns[i] < 0)||(columnSize <= columns[i])) return true;
    }
    return false;
  }
 
  protected void setValues(Object[][] target, Object value,
                           int[] rows, int[] columns) {
    for (int i=0;i<rows.length;i++) {
      int row = rows[i];
      for (int j=0;j<columns.length;j++) {
        int column = columns[j];
        target[row][column] = value;
      }
    }
  }
}

CellAttribute.java:

import java.awt.*;
 
/**
 * @version 1.0 11/22/98
 */ 
public interface CellAttribute {
 
  public void addColumn();
 
  public void addRow();
 
  public void insertRow(int row);
 
  public Dimension getSize();
 
  public void setSize(Dimension size);
}

ColoredCell.java:

import java.awt.*;
 
/**
 * @version 1.0 11/22/98
 */
 
public interface ColoredCell {
  public Color getForeground(int row, int column);
  public void setForeground(Color color, int row, int column);
  public void setForeground(Color color, int[] rows, int[] columns);
 
  public Color getBackground(int row, int column);
  public void setBackground(Color color, int row, int column);
  public void setBackground(Color color, int[] rows, int[] columns);
}

CellFont.java:

import java.awt.*;
 
/**
 * @version 1.0 11/22/98
 */
 
public interface CellFont {
  public Font getFont(int row, int column);
  public void setFont(Font font, int row, int column);
  public void setFont(Font font, int[] rows, int[] columns);
}

CellSpan.java:

/**
 * @version 1.0 11/22/98
 */
 
public interface CellSpan {
  public final int ROW    = 0;
  public final int COLUMN = 1;
   
  public int[] getSpan(int row, int column);
  public void setSpan(int[] span, int row, int column);
   
  public boolean isVisible(int row, int column);
   
  public void combine(int[] rows, int[] columns);
  public void split(int row, int column);

}

MultiSpanCellTable.java:

import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.*;
import javax.swing.event.*;
 
/**
 * @version 1.0 11/26/98
 */
 
public class MultiSpanCellTable extends JTable {
 
  public MultiSpanCellTable(TableModel model) {
    super(model);
    setUI(new MultiSpanCellTableUI());
    getTableHeader().setReorderingAllowed(false);
    setCellSelectionEnabled(true);
    setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
  }
  
  public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
    Rectangle sRect = super.getCellRect(row,column,includeSpacing);
    if ((row <0) || (column<0) ||
        (getRowCount() <= row) || (getColumnCount() <= column)) {
        return sRect;
    }
    CellSpan cellAtt = (CellSpan)((AttributiveCellTableModel)getModel()).getCellAttribute();
    if (! cellAtt.isVisible(row,column)) {
      int temp_row    = row;
      int temp_column = column;
      row    += cellAtt.getSpan(temp_row,temp_column)[CellSpan.ROW];
      column += cellAtt.getSpan(temp_row,temp_column)[CellSpan.COLUMN];      
    }
    int[] n = cellAtt.getSpan(row,column);
 
    int index = 0;
    int columnMargin = getColumnModel().getColumnMargin();
    Rectangle cellFrame = new Rectangle();
    int aCellHeight = rowHeight + rowMargin;
    cellFrame.y = row * aCellHeight;
    cellFrame.height = n[CellSpan.ROW] * aCellHeight;
    
    Enumeration enumeration = getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
      TableColumn aColumn = (TableColumn)enumeration.nextElement();
      cellFrame.width = aColumn.getWidth() + columnMargin;
      if (index == column) break;
      cellFrame.x += cellFrame.width;
      index++;
    }
    for (int i=0;i< n[CellSpan.COLUMN]-1;i++) {
      TableColumn aColumn = (TableColumn)enumeration.nextElement();
      cellFrame.width += aColumn.getWidth() + columnMargin;
    }
     
    if (!includeSpacing) {
      Dimension spacing = getIntercellSpacing();
      cellFrame.setBounds(cellFrame.x +      spacing.width/2,
                          cellFrame.y +      spacing.height/2,
                          cellFrame.width -  spacing.width,
                          cellFrame.height - spacing.height);
    }
    return cellFrame;
  }
  
  
  private int[] rowColumnAtPoint(Point point) {
    int[] retValue = {-1,-1};
    int row = point.y / (rowHeight + rowMargin);
    if ((row <0)||(getRowCount() <= row)) return retValue;
    int column = getColumnModel().getColumnIndexAtX(point.x);
 
    CellSpan cellAtt = (CellSpan)((AttributiveCellTableModel)getModel()).getCellAttribute();
 
    if (cellAtt.isVisible(row,column)) {
      retValue[CellSpan.COLUMN] = column;
      retValue[CellSpan.ROW   ] = row;
      return retValue;
    }
    retValue[CellSpan.COLUMN] = column + cellAtt.getSpan(row,column)[CellSpan.COLUMN];
    retValue[CellSpan.ROW   ] = row + cellAtt.getSpan(row,column)[CellSpan.ROW];
    return retValue;
  }
 
  public int rowAtPoint(Point point) {
    return rowColumnAtPoint(point)[CellSpan.ROW];
  }
  public int columnAtPoint(Point point) {
    return rowColumnAtPoint(point)[CellSpan.COLUMN];
  }
 
 
  
  public void columnSelectionChanged(ListSelectionEvent e) {
    repaint();
  }
 
  public void valueChanged(ListSelectionEvent e) {
    int firstIndex = e.getFirstIndex();
    int  lastIndex = e.getLastIndex();
    if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
      repaint();
    }
    Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
    int numCoumns = getColumnCount();
    int index = firstIndex;
    for (int i=0;i<numCoumns;i++) {
      dirtyRegion.add(getCellRect(index, i, false));
    }
    index = lastIndex;
    for (int i=0;i<numCoumns;i++) {
      dirtyRegion.add(getCellRect(index, i, false));
    }
    repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  }
 
}

MultiSpanCellTableUI.java:

import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.*;
 
/**
 * @version 1.0 11/26/98
 */
 
public class MultiSpanCellTableUI extends BasicTableUI {
 
  public void paint(Graphics g, JComponent c) {
    Rectangle oldClipBounds = g.getClipBounds();
    Rectangle clipBounds    = new Rectangle(oldClipBounds);
    int tableWidth   = table.getColumnModel().getTotalColumnWidth();
    clipBounds.width = Math.min(clipBounds.width, tableWidth);
    g.setClip(clipBounds);
 
    int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
    int  lastIndex = table.getRowCount()-1;
 
    Rectangle rowRect = new Rectangle(0,0,
      tableWidth, table.getRowHeight() + table.getRowMargin());
    rowRect.y = firstIndex*rowRect.height;
 
    for (int index = firstIndex; index <= lastIndex; index++) {
      if (rowRect.intersects(clipBounds)) {
        //System.out.println();                  // debug
        //System.out.print("" + index +": ");    // row
        paintRow(g, index);
      }
      rowRect.y += rowRect.height;
    }
    g.setClip(oldClipBounds);
  }
 
  private void paintRow(Graphics g, int row) {
    Rectangle rect = g.getClipBounds();
    boolean drawn  = false;
    
    AttributiveCellTableModel tableModel = (AttributiveCellTableModel)table.getModel();
    CellSpan cellAtt = (CellSpan)tableModel.getCellAttribute();
    int numColumns = table.getColumnCount();
 
    for (int column = 0; column < numColumns; column++) {
      Rectangle cellRect = table.getCellRect(row,column,true);
      int cellRow,cellColumn;
      if (cellAtt.isVisible(row,column)) {
        cellRow    = row;
        cellColumn = column;
          //  System.out.print("   "+column+" ");  // debug
      } else {
        cellRow    = row + cellAtt.getSpan(row,column)[CellSpan.ROW];
        cellColumn = column + cellAtt.getSpan(row,column)[CellSpan.COLUMN];
          //  System.out.print("  ("+column+")");  // debug
      }
      if (cellRect.intersects(rect)) {
        drawn = true;
        paintCell(g, cellRect, cellRow, cellColumn);
      } else {
        if (drawn) break;
      } 
    }
  }
 
  private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
    int spacingHeight = table.getRowMargin();
    int spacingWidth  = table.getColumnModel().getColumnMargin();
 
    Color c = g.getColor();
    g.setColor(table.getGridColor());
    g.drawRect(cellRect.x,cellRect.y,cellRect.width-1,cellRect.height-1);
    g.setColor(c);
 
    cellRect.setBounds(cellRect.x + spacingWidth/2, cellRect.y + spacingHeight/2,
                       cellRect.width - spacingWidth, cellRect.height - spacingHeight);
 
    if (table.isEditing() && table.getEditingRow()==row &&
        table.getEditingColumn()==column) {
      Component component = table.getEditorComponent();
      component.setBounds(cellRect);
      component.validate();
    }
    else {
      TableCellRenderer renderer = table.getCellRenderer(row, column);
      Component component = table.prepareRenderer(renderer, row, column);
 
      if (component.getParent() == null) {
        rendererPane.add(component);
      }
      rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
                                  cellRect.width, cellRect.height, true);
    }
  }    
}

Adding a MouseListener to every row in a JTable

Here’s an code sample:

Main.java:

import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
 
public class Main extends JFrame {
   public Main() {
      super("TableModel Demonstration");
 
      // create our own custom TableModel
      WineTableModel wineModel = new WineTableModel();
      final JTable table = new JTable(wineModel);
 
      // add rows to our TableModel, each row is represented as a Wine object
      wineModel.addWine(new Wine("Chateau Meyney, St. Estephe", "1994", 18.75f, true));
      wineModel.addWine(new Wine("Chateau Montrose, St. Estephe", "1975", 54.25f, true));
      wineModel.addWine(new Wine("Chateau Gloria, St. Julien", "1993", 22.99f, false));
      wineModel.addWine(new Wine("Chateau Beychevelle, St. Julien", "1970", 61.63f, false));
      wineModel.addWine(new Wine("Chateau La Tour de Mons, Margeaux", "1975", 57.03f, true));
      wineModel.addWine(new Wine("Chateau Brane-Cantenac, Margeaux", "1978", 49.92f, false));
 
      // create the scroll pane and add the table to it. 
      JScrollPane scrollPane = new JScrollPane(table);
 
      // add the scroll pane to this window.
      getContentPane().add(scrollPane, BorderLayout.CENTER);
 
      table.addMouseListener(new MouseAdapter() {
         public void mouseReleased(MouseEvent me) {
            int row = table.rowAtPoint(me.getPoint());
            System.out.println("You clicked at row " + row);
         }
      });
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String[] args) {
      Main main = new Main();
      main.pack();
      main.setVisible(true);
   }
}
 
// a simple object that holds data about a particular wine
class Wine {
   private String  name;
   private String  vintage;
   private float   price;
   private boolean inStock;
 
   public Wine(String name, String vintage, float price, boolean inStock) {
      this.name = name;
      this.vintage = vintage;
      this.price = price;
      this.inStock = inStock;
   }
 
   public String getName()     { return name; }
   public String getVintage()  { return vintage; }
   public float  getPrice()    { return price; } 
   public boolean getInStock() { return inStock; }
 
   public String toString() { 
      return "[" + name + ", " + vintage + ", " + price + ", " + inStock + "]"; }
}
 
class WineTableModel extends AbstractTableModel {
   // holds the strings to be displayed in the column headers of our table
   final String[] columnNames = {"Name", "Vintage", "Price", "In stock?"};
 
   // holds the data types for all our columns
   final Class[] columnClasses = {String.class, String.class, Float.class, Boolean.class};
 
   // holds our data
   final Vector data = new Vector();
  
   // adds a row
   public void addWine(Wine w) {
      data.addElement(w);
      fireTableRowsInserted(data.size()-1, data.size()-1);
   }
 
   public int getColumnCount() {
      return columnNames.length;
   }
         
   public int getRowCount() {
      return data.size();
   }
 
   public String getColumnName(int col) {
      return columnNames[col];
   }
 
   public Class getColumnClass(int c) {
      return columnClasses1;
   }
 
   public Object getValueAt(int row, int col) {
      Wine wine = (Wine) data.elementAt(row);
      if (col == 0)      return wine.getName();
      else if (col == 1) return wine.getVintage();
      else if (col == 2) return new Float(wine.getPrice());
      else if (col == 3) return new Boolean(wine.getInStock());
      else return null;
   }
 
   public boolean isCellEditable(int row, int col) {
      return false;
   }
}

Changing the icons of a JTree

Just use the methods setOpenIcon, setClosedIcon and setLeafIcon defined in the DefaultCellRenderer class.

Here’s an example.

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
      DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
      root.add(child1);
      DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2");
      root.add(child2);
      JTree tree = new JTree(root);
 
      DefaultTreeCellRenderer cr = new DefaultTreeCellRenderer();
      cr.setOpenIcon(new ImageIcon("openicon.jpg"));
      cr.setClosedIcon(new ImageIcon("closedicon.jpg"));
      cr.setLeafIcon(new ImageIcon("leaficon.jpg"));
  
      tree.setCellRenderer(cr);
 
      getContentPane().add(new JScrollPane(tree));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

The icons used in this program: