|
||
/** * EventCellTable.java * * Copyright 2003 by Christina Schulman * * This code has been tested under JDK 1.3.1, but might act * strangely under other versions of the JDK. * * Disclaimer: This code is provided "as is"; all warranties * express and implied are disclaimed; I am not liable for * anything you do with this, ever; do not take internally; * do not taunt Happy Fun Ball. * * For more code samples, see http://www.epiphyte.net/dev/. */ package net.epiphyte.sample.gui.EventCellTable; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BoxLayout; import javax.swing.AbstractCellEditor; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import java.util.EventObject; import java.util.Hashtable; /** * EventCellTable is a simple stand-alone example of a JTable * that can display AWT/Swing Components in its cells, and * allows those components (and their contents) to receive * events. * * This example uses ActionEvents. Other events can also * be used, although MouseEvent enter and exit events are * not always reliably generated. * * @author Christina Schulman * @author http://www.epiphyte.net * @version 1.0 * @see javax.swing.JTable * @see javax.swing.table.TableCellEditor * @see javax.swing.table.TableCellRenderer * @since 12 May 2003 */ public class EventCellTable extends JTable { /** * Creates an EventCellTable within a JFrame. * * @param args Command-line args (ignored). */ public static void main(String args[]) { // Create a frame to display the demo JFrame frame = new JFrame("EventCellTable demo"); frame.setSize(600, 200); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(false); // Center the frame on the screen Dimension sd = Toolkit.getDefaultToolkit().getScreenSize(); Dimension fd = frame.getSize(); frame.setLocation((sd.width/2)-(fd.width/2), (sd.height/2)-(fd.height/2)); // Create & add the EventCellTable frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add((new JScrollPane(new EventCellTable())), BorderLayout.CENTER); frame.setVisible(true); } /** * Create an EventCellTable. Dummy data and components are * hardcoded, because it's just a little demo. */ public EventCellTable() { final int NUM_ROWS = 9; final String[] columnNames = {"single button", "button panel", "just some text"}; int numCols = columnNames.length; Object[][] values = new Object[0][numCols]; // Initialize the table model with the column headers setModel(new DefaultTableModel(values, columnNames)); // Cosmetic settings. Mess with these if you want to change // how other cells in the row are highlighted when the user // clicks on a button in a component cell. setRowSelectionAllowed(true); setColumnSelectionAllowed(false); // Create single instances of the cell renderer and cell // editor. These will be used for component-based columns, // but not for the text column, which just uses the // default cell renderer and editor. ComponentRenderer cellrenderer = new ComponentRenderer(); ComponentEditor celleditor = new ComponentEditor(); // Set component-aware renderer and editor for single-button column getColumnModel().getColumn(0).setCellRenderer(cellrenderer); getColumnModel().getColumn(0).setCellEditor(celleditor); // Set component-aware renderer and editor for button-panel column getColumnModel().getColumn(1).setCellRenderer(cellrenderer); getColumnModel().getColumn(1).setCellEditor(celleditor); // Add data to the table, including components for (int row = 0; row < NUM_ROWS; row++) { // Add the new row String[] rowData = new String[getModel().getColumnCount()]; rowData[2] = "value for row #" + row; ((DefaultTableModel) getModel()).addRow(rowData); // Add the new components setValueAt((new CellButton("button " + row)),row,0); setValueAt((new CellPanel("panel " + row)),row,1); } } /** * Inner class ComponentRenderer * * Renderer that allows AWT/Swing components to display correctly. */ class ComponentRenderer implements TableCellRenderer { /** * Returns the component used for drawing the cell. This method is * used to configure the renderer appropriately before drawing. * * @param table The invoking JTable; can be null. * @param value The value of the cell to be rendered. Here, the component. * @param isSelected True if the cell should to be highlighted. * @param hasFocus True if the cell currently has the editing focus. * @param row The row index of the cell being drawn. * @param column The column index of the cell being drawn. * * @return The value itself, cast to a Component, since it can render itself. */ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (value instanceof Component) { return (Component) value; } else { return null; } } } /** * Cell editor that lets AWT/Swing components receive events. */ class ComponentEditor extends AbstractCellEditor implements TableCellEditor { /** * Stores the component currently being edited. */ Component comp_ = null; /** * Returns the value contained in the editor. * * @return The component value currently being edited. */ public Object getCellEditorValue() { return comp_; } /** * Sets an initialvalue
for the editor. This will cause * the editor tostopEditing
and lose any partially * edited value if the editor is editing when this method is called.* * Returns the component that should be added to the client's *
Component
hierarchy. Once installed in the client's * hierarchy this component will then be able to draw and receive * user input. * * @param table The invoking JTable; can be null. * @param value The value of the cell to be edited. Here, the component. * @param isSelected True if the cell should to be highlighted. * @param row The row of the cell being edited. * @param column The column of the cell being edited. * * @return The component itself, so that it can receive user events. */ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { if (value instanceof Component) { comp_ = (Component) value; return (Component) value; } else { return null; } } } /** * Example button class that handles its own Action Events. * * When the button is pressed, a message box pops up with the button's title. */ class CellButton extends JButton implements ActionListener { /** * Creates a button with the supplied title, and adds itself * as its own ActionListener. * * @param szText Button title. */ public CellButton(String szText) { super(szText); addActionListener(this); } /** * Invoked when this button is pressed; just displays a thrilling * message box to tell the user which button was pressed. * * @param e ActionEvent that fired this method. */ public void actionPerformed(ActionEvent e) { if ((e != null) && (e.getSource() == this)) { JOptionPane.showMessageDialog(null, getText() + " was pressed!"); } } } /** * Example panel that contains a couple of buttons. */ class CellPanel extends JPanel { /** * Creates a panel that contains two CellButtons, laid out horizontally. * * @param szText Panel title, used to give its buttons * unique (hopefully) names. */ public CellPanel(String szText) { setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); add(new CellButton(szText + "-A")); add(new CellButton(szText + "-B")); } } }