/* * Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package components;/* * TableRenderDemo.java requires no other files. */import javax.swing.DefaultCellEditor;import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTable;import javax.swing.table.AbstractTableModel;import javax.swing.table.DefaultTableCellRenderer;import javax.swing.table.TableCellRenderer;import javax.swing.table.TableColumn;import java.awt.Component;import java.awt.Dimension;import java.awt.GridLayout;/** * TableRenderDemo is just like TableDemo, except that it explicitly initializes * column sizes and it uses a combo box as an editor for the Sport column. */public class TableRenderDemo extends JPanel { /** * */ private static final long serialVersionUID = 1L; private boolean DEBUG = true; private JTable table; public TableRenderDemo() { super(new GridLayout(1, 0)); table = new JTable(new MyTableModel()); table.setPreferredScrollableViewportSize(new Dimension(500, 70)); table.setFillsViewportHeight(true); // Create the scroll pane and add the table to it. JScrollPane scrollPane = new JScrollPane(table); // Set up column sizes. initColumnSizes(table); // Fiddle with the Sport column's cell editors/renderers. setUpSportColumn(table, table.getColumnModel().getColumn(2)); // Add the scroll pane to this panel. add(scrollPane); } /* * This method picks good column sizes. If all column heads are wider than * the column's cells' contents, then you can just use * column.sizeWidthToFit(). */ private void initColumnSizes(JTable table) { MyTableModel model = (MyTableModel) table.getModel(); TableColumn column = null; Component comp = null; int headerWidth = 0; int cellWidth = 0; Object[] longValues = model.longValues; TableCellRenderer headerRenderer = table.getTableHeader() .getDefaultRenderer(); for (int i = 0; i < 5; i++) { column = table.getColumnModel().getColumn(i); comp = headerRenderer.getTableCellRendererComponent(null, column .getHeaderValue(), false, false, 0, 0); headerWidth = comp.getPreferredSize().width; comp = table.getDefaultRenderer(model.getColumnClass(i)) .getTableCellRendererComponent(table, longValues[i], false, false, 0, i); cellWidth = comp.getPreferredSize().width; if (DEBUG) { System.out.println("Initializing width of column " + i + ". " + "headerWidth = " + headerWidth + "; cellWidth = " + cellWidth); } column.setPreferredWidth(Math.max(headerWidth, cellWidth)); } } public void setUpSportColumn(JTable table, TableColumn sportColumn) { // Set up the editor for the sport cells. JComboBox comboBox = new JComboBox(); comboBox.addItem("Snowboarding"); comboBox.addItem("Rowing"); comboBox.addItem("Knitting"); comboBox.addItem("Speed reading"); comboBox.addItem("Pool"); comboBox.addItem("None of the above"); sportColumn.setCellEditor(new DefaultCellEditor(comboBox)); // Set up tool tips for the sport cells. DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); renderer.setToolTipText("Click for combo box"); sportColumn.setCellRenderer(renderer); } class MyTableModel extends AbstractTableModel { private String[] columnNames = { "First Name", "Last Name", "Sport", "# of Years", "jo", "nope" }; private Object[][] data = { { "Mary", "Campione", "Snowboarding", new Integer(5), new Boolean(false), new Boolean(true), new Boolean(false) }, { "Alison", "Huml", "Rowing", new Integer(3), new Boolean(true), new Boolean(false) }, { "Kathy", "Walrath", "Knitting", new Integer(2), new Boolean(false), new Boolean(true) }, { "Sharon", "Zakhour", "Speed reading", new Integer(20), new Boolean(true), new Boolean(false) }, { "Philip", "Milne", "Pool", new Integer(10), new Boolean(false), new Boolean(true) } }; public final Object[] longValues = { "Sharon", "Campione", "None of the above", new Integer(20), Boolean.TRUE, Boolean.FALSE }; public int getColumnCount() { return columnNames.length; } public int getRowCount() { return data.length; } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { return data[row][col]; } /* * JTable uses this method to determine the default renderer/ editor for * each cell. If we didn't implement this method, then the last column * would contain text ("true"/"false"), rather than a check box. */ public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } /* * Don't need to implement this method unless your table's editable. */ public boolean isCellEditable(int row, int col) { // Note that the data/cell address is constant, // no matter where the cell appears onscreen. if (col < 2) { return false; } else { return true; } } /* * Don't need to implement this method unless your table's data can * change. */ public void setValueAt(Object value, int row, int col) { if (DEBUG) { System.out.println("Setting value at " + row + "," + col + " to " + value + " (an instance of " + value.getClass() + ")"); } switch (col) { case 4: Boolean complement = !((Boolean)value); System.out.println("Complement: " + complement.toString()); data[row][5] = complement; table.repaint(); case 5: data[row][4] = !((Boolean)value); table.repaint(); } data[row][col] = value; fireTableCellUpdated(row, col); if (DEBUG) { System.out.println("New value of data:"); printDebugData(); } } private void printDebugData() { int numRows = getRowCount(); int numCols = getColumnCount(); for (int i = 0; i < numRows; i++) { System.out.print(" row " + i + ":"); for (int j = 0; j < numCols; j++) { System.out.print(" " + data[i][j]); } System.out.println(); } System.out.println("--------------------------"); } } /** * Create the GUI and show it. For thread safety, this method should be * invoked from the event-dispatching thread. */ private static void createAndShowGUI() { // Create and set up the window. JFrame frame = new JFrame("TableRenderDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Create and set up the content pane. TableRenderDemo newContentPane = new TableRenderDemo(); newContentPane.setOpaque(true); // content panes must be opaque frame.setContentPane(newContentPane); // Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { // Schedule a job for the event-dispatching thread: // creating and showing this application's GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); }}