L&F mapping JTable

The look and feel values chosen for the JTable under windows do not feel right to me (albeit that I cannot find many examples of tables under windows).
I am trying to provide some workarounds that follow what most people expect to happen but am a little unclear on what should happen on some key presses for the JTable in windows look and feel
Space handling
From one of the MS windows books it suggests that the space key is a selection key, thus when you press space a row in a table should be selected (and when you press again it should deselect the row?)
The JList has functionality for the space key
q1) JTable should have space bar handling out of the box?
(space, CTRL+space, shift+space)
I have not seen this raised as a bug.
Enter handling
The enter key press is supposed to activate the default button
or commit a text field under edit.
F2 puts a field under edit
q2) Should the enter key put an editable cell under edit (same mouse action as single or double click to edit)?
q3) if not should the first enter key stop cell editing and a second press activate the default button, with only a single enter to activate default button if a cell is not under edit
Escape handling
The escape key will cancel editing of a cell that is under edit.
q4) should the event not be passed on when editing has been cancelled so that dialogs with a canel button can be dismissed
or
q5) should the first escape cancel editing while the second escape will action the escape action of the window.
Any links to "highly regarded" useability/look and feel sites would be helpful - sun does not appear to provide much on this subject
I've read both their l&f and advanced l&f books and they just scratch the surface of look and feel without much realworld appliance to real gui issues.
Might be useful to others: Some of the code that I was trying to create goes like....
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.CellEditor;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
/** Provides utility methods for the JTable and JCSortableTable classes
* @author  */
public final class JTableUtil
      * Constructor for JCTableUtil.
     private JTableUtil()
          super();
     /** will resize the last column of a table to fill the gap
      * if the width of the columns is narrower than the width of the
      * table
      * @param table to act upon
     static void resizeLastColumn(final JTable table)
          TableColumn lastColumn = getLastVisibleColumn(table);
          if (lastColumn != null)
               int gap = getLastColumnGap(table);
               if (gap > 0)
                    int newLastColumnWidth = gap + lastColumn.getWidth();
                    lastColumn.setWidth(newLastColumnWidth);
                    lastColumn.setPreferredWidth(newLastColumnWidth);
                    redrawTable(table);
      * Determines if there is a gap between the last column in a table
      * and the border of the table.
      * Works if the table is drawn on the page or is in the
      * viewport of a scroll pane.
      * @param table to act upon
      * @return the gap in pixels between last column and table edge.
     static int getLastColumnGap(final JTable table)
          int widthTable = getTableWidth(table);
          int lastVisColIndex = getLastVisibleColumnIndex(table);
          TableColumnModel columnModel = table.getColumnModel();
          int widthColumns = columnModel.getTotalColumnWidth();
          final TableColumn lastColumn = columnModel.getColumn(lastVisColIndex);
          // gap is number of pixels from right hand edge of last column
          // to right hand edge of the table
          int gap = widthTable - widthColumns;
          return gap;
      * Determines the width of a table returning the table width if
      * table is painted onto a panel, but if the table is painted
      * into a scroll pane then it is the scroll pane viewport width that is returned
      * This is to capture that the width of the table may be less than the
      * width of the viewport - ie if there is a gap after the last column in a table.
      * @param table to act upon
      * @return the width of the table in pixels
     static int getTableWidth(final JTable table)
          int widthTable = table.getWidth();
          Object tableParent = table.getParent();
          JViewport tableViewPort = null;
          if (tableParent instanceof JViewport)
               tableViewPort = (JViewport) tableParent;
               widthTable = tableViewPort.getWidth();
          return widthTable;
     /** Cause the table to redraw wether table is painted on a panel
      * or in a scroll pane
      * @param table to act upon
     static void redrawTable(final JTable table)
          Component tableRegion = table;
          Component tableParent = table.getParent();
          if (tableParent instanceof JViewport)
               tableRegion = tableParent;
          tableRegion.invalidate();
          tableRegion.validate();
     /** Determines the last (right most) column in a table with a width
      * greater than 0
      * @param table to act upon
      * @return index (0 based) of the last visible column.
     static int getLastVisibleColumnIndex(JTable table)
          TableColumnModel columnModel = table.getColumnModel();
          boolean found = false;
          int columnIndex = columnModel.getColumnCount();
          while (!found && columnIndex > 0)
               columnIndex--;
               if (columnModel.getColumn(columnIndex).getWidth() != 0)
                    found = true;
          return columnIndex;
     /** Determines the last (right most) column in a table with a width
      * greater than 0
      * @param table to act upon
      * @return TableColumn - the last visible column.
     static TableColumn getLastVisibleColumn(JTable table)
          TableColumnModel columnModel = table.getColumnModel();
          return columnModel.getColumn(getLastVisibleColumnIndex(table));
      * Add the currency symbol to a JCTable/JCListTable column header
      * e.g. 'Salary' becomes 'Salary (�)'
     public static void addCurrencySymbol(JTable table, Object columnKey)
          //@todo - update to work with JTable
          TableColumnModel columnModel = table.getTableHeader().getColumnModel();
          int columnIndex = columnModel.getColumnIndex(columnKey);
          TableColumn column = columnModel.getColumn(columnIndex);
          Object object = column.getHeaderValue();
          if (object instanceof JLabel)
               JLabel columnLabel = (JLabel) object;
               SlacCurrency.getInstance().addCurrencySymbol(columnLabel);
          else
               // @todo log here ???
          // is above correct - need to get the JLabel rendered from the table
          // in the scroll pane?          
     /** Provides a sum of a column of BigDecimals
      * @param tableModel model containing column that you wish to sum
      * @param column the column that you wish to be summed, must contain numeric values and not strings
     public static BigDecimal calculateTotalForColumn(final TableModel tableModel, final int column)
          int numRows = tableModel.getRowCount();
          BigDecimal total = new BigDecimal("0");
          for (int row = 0; row < numRows; row++)
               Object value = tableModel.getValueAt(row, column);
               if (value instanceof BigDecimal)
                    BigDecimal decimalValue = (BigDecimal) value;
                    total = total.add(decimalValue);
               else
                    //Logger.logGeneralFailure("", ErrorCodes.GUI_ERROR, this);
          return total;
      * Provides the swing setting JTable.AUTO_RESIZE_OFF.
      * <p>
      * In this situation if the width of the columns is smaller than the width
      * of the table then there will be a gap after the last column.
      * <p>
      * This method will add a ComponentListener to the table and or
      * scroll pane viewport so that there is no gap after the last column.
      * @param table to act upon
     public static void configureAutoResizeOff(final JTable table)
          table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
          Component tableParent = table.getParent();
          JViewport tableViewPort = null;
          ComponentAdapter gapFiller = new ComponentAdapter()
               public void componentResized(ComponentEvent e)
                    super.componentResized(e);
                    JTableUtil.resizeLastColumn(table);
          table.addComponentListener(gapFiller);
          if (tableParent instanceof JViewport)
               tableViewPort = (JViewport) tableParent;
               tableViewPort.addComponentListener(gapFiller);
     /** Method provides fixes to provide standard handling for keyboard and mouse usage
      * <ul>
      *    <li> spacebar - selection handling of rows that have focus emphasis see fixSpacebarHandling()
      *    <li> initial focus handling - table should give visual feedback when gaining focus
      *    <li>
      * </ul>
      * @param table - the table to add standards handling to
     public static void setupKeyboardMouseHandling(JTable table)
          fixTableGainsFocusOnFirstEntry(table);
          fixSpacebarHandling(table);
          fixCtrlSpacebarHandling(table);
          fixShiftSpacebarHandling(table);
          fixCtrlUpDownHandling(table);
          fixFocusHighlight();
          fixEscEnter(table);
     /** Add fixes to the look and feel handling for a JTable
      * Enter on a table will do different things depending on the mode of the table
      * <p>
      * if a cell is being edited then
      * Enter will do what normally happens to a field under edit - ie stop the editing and commit
      * Escape will cancel the editing
      * <p>
      * if a cell is not under edit then
      * Enter will activate the default button
      * Escape will activate the default cancel button (see FrameUtil.addEscapeKeyAction())
     static void fixEscEnter(final JTable table)
          final RootPaneContainer root = (RootPaneContainer)SwingUtilities.windowForComponent(table);
          final String escapeKey = "escapeAction";
          Action escapeAction = new AbstractAction(escapeKey)
               public void actionPerformed(ActionEvent actionEvent)
                    if(table.isEditing())
                         CellEditor editor = table.getCellEditor(table.getEditingRow(), table.getEditingColumn());
                         editor.cancelCellEditing();
                    else
                         Window parentWindow = SwingUtilities.windowForComponent(table);
                         Action windowEscapeAction = FrameUtil.getEscapeKeyAction(root);
                         windowEscapeAction.actionPerformed(actionEvent);
          final String enterKey = "enterAction";
          Action enterAction = new AbstractAction(enterKey)
               public void actionPerformed(ActionEvent actionEvent)
                    if(table.isEditing())
                         CellEditor editor = table.getCellEditor(table.getEditingRow(), table.getEditingColumn());
                         editor.stopCellEditing();
                    else
                         root.getRootPane().getDefaultButton().doClick();
          InputMap inputMap = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
          table.getActionMap().put(escapeKey, escapeAction);
          table.getActionMap().put(enterKey, enterAction);
          inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), escapeKey);          
          inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), enterKey);          
     static void fixFocusHighlight()
          Border focusCellHighlightBorder = new DashedLineBorder(Color.BLACK);
          UIManager.put("Table.focusCellHighlightBorder", focusCellHighlightBorder);
     /** If you do not setup a table to have a row selected then there is a bug where for example
      * you use an accelerator key to put focus in the table and you get no visual feedback that
      * the table has focus - ie no focus emphasis - dashed box
      * @param table - the table to fix
     static void fixTableGainsFocusOnFirstEntry(JTable table)
          // for first time tabbing to table make sure that first cell has focus
          // don't seem to need this fix under windows XP
          table.getSelectionModel().removeSelectionInterval(0, 0);
     /** fix spacebar handling
      * java standards does not mention spacebar handling on a JTable but this is a windows
      * standard feature and is also a feature on JList.
      * Without spacebar handling on a JTable there would be no other keyboard handling that
      * would allow you to select the current row.
      * <p>
      * Trying to follow windows standards since java does not list space bar handling for JTable.
      * The following bahaviour can be seen in IBM code in project Java build path - tab libraries
      * and in microsoft code in the administrative tools control panel dialog in windows XP
      * <p>
      * spacebar - select the current row without deselecting any others
      * <p>
      * handling should be fixed in merlin release 1.5
      * see bug report http://developer.java.sun.com/developer/bugParade/bugs/4303294.html
     static void fixSpacebarHandling(JTable table)
          KeyStroke ksSpace = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true);
          final String ACTION_SPACE = "SPACE";
          Action spaceAction = new AbstractAction(ACTION_SPACE)
               public void actionPerformed(ActionEvent actionEvent)
                    ListSelectionModel selectModel =
                         ((JTable) actionEvent.getSource()).getSelectionModel();
                    int currentRowIndex = selectModel.getAnchorSelectionIndex();
                    selectModel.addSelectionInterval(currentRowIndex, currentRowIndex);
          table.getInputMap().put(ksSpace, ACTION_SPACE);
          table.getActionMap().put(ACTION_SPACE, spaceAction);
     /** fix ctrl + spacebar handling
      * java standards does not mention spacebar handling on a JTable but this is a windows
      * standard feature and is also a feature on JList.
      * Without spacebar handling on a JTable there would be no other keyboard handling that
      * would allow you to select the current row.
      * <p>
      * Trying to follow windows standards since java does not list space bar handling for JTable.
      * The following bahaviour can be seen in IBM code in project Java build path - tab libraries
      * and in microsoft code in the administrative tools control panel dialog in windows XP
      * <p>
      * ctrl + spacebar - toggle selection on the current row without deselecting any others
      * <p>
      * handling should be fixed in merlin release 1.5
      * see bug report http://developer.java.sun.com/developer/bugParade/bugs/4303294.html
     static void fixCtrlSpacebarHandling(JTable table)
          KeyStroke ksCtrlSpace = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, Event.CTRL_MASK, true);
          final String ACTION_CTRL_SPACE = "CTRLSPACE";
          Action ctrlSpaceAction = new AbstractAction(ACTION_CTRL_SPACE)
               public void actionPerformed(ActionEvent actionEvent)
                    ListSelectionModel selectModel =
                         ((JTable) actionEvent.getSource()).getSelectionModel();
                    int currentRowIndex = selectModel.getAnchorSelectionIndex();
                    boolean isCurrentRowSelected = selectModel.isSelectedIndex(currentRowIndex);
                    if (isCurrentRowSelected)
                         selectModel.removeSelectionInterval(currentRowIndex, currentRowIndex);
                    else
                         selectModel.addSelectionInterval(currentRowIndex, currentRowIndex);
          table.getInputMap().put(ksCtrlSpace, ACTION_CTRL_SPACE);
          table.getActionMap().put(ACTION_CTRL_SPACE, ctrlSpaceAction);
     /** fix shift + spacebar handling
      * java standards does not mention spacebar handling on a JTable but this is a windows
      * standard feature and is also a feature on JList.
      * Without spacebar handling on a JTable there would be no other keyboard handling that
      * would allow you to select the current row.
      * <p>
      * Trying to follow windows standards since java does not list space bar handling for JTable.
      * The following bahaviour can be seen in IBM code in project Java build path - tab libraries
      * and in microsoft code in the administrative tools control panel dialog in windows XP
      * <p>
      * shift + spacebar - extend the selection from the anchor to the lead index.
      * this might still be a bit funny in java 1.4.2 and code may need to be changed slightly
      * <p>
      * handling should be fixed in merlin release 1.5
      * see bug report http://developer.java.sun.com/developer/bugParade/bugs/4303294.html
     static void fixShiftSpacebarHandling(JTable table)
          KeyStroke ksShiftSpace = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, Event.SHIFT_MASK, true);
          final String ACTION_SHIFT_SPACE = "SHIFTSPACE";
          Action shiftSpaceAction = new AbstractAction(ACTION_SHIFT_SPACE)
               public void actionPerformed(ActionEvent actionEvent)
                    ListSelectionModel selectModel =
                         ((JTable) actionEvent.getSource()).getSelectionModel();
                    int currentRowIndex = selectModel.getAnchorSelectionIndex();
                    int startRowIndex = selectModel.getLeadSelectionIndex();
                    selectModel.setSelectionInterval(startRowIndex, currentRowIndex);
          table.getInputMap().put(ksShiftSpace, ACTION_SHIFT_SPACE);
          table.getActionMap().put(ACTION_SHIFT_SPACE, shiftSpaceAction);
     /** fix ctrl + down or up handling - move focus emphasis up or down accordingly
      * <p>
      * handling should be fixed in merlin release 1.5
      * see bug report http://developer.java.sun.com/developer/bugParade/bugs/4303294.html
     static void fixCtrlUpDownHandling(JTable table)
          final String ACTION_UP = "CTRLUP";
          KeyStroke ksCtrlUp = KeyStroke.getKeyStroke(KeyEvent.VK_UP, Event.CTRL_MASK, true);
          KeyStroke ksCtrlDown = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, Event.CTRL_MASK, true);
          Action ctrlUpAction = new CtrlUpDownAction(ACTION_UP, true);
          final String ACTION_DOWN = "CTRLDOWN";
          Action ctrlDownAction = new CtrlUpDownAction(ACTION_DOWN, false);
          table.getInputMap().put(ksCtrlUp, ACTION_UP);
          table.getActionMap().put(ACTION_UP, ctrlUpAction);
          table.getInputMap().put(ksCtrlDown, ACTION_DOWN);
          table.getActionMap().put(ACTION_DOWN, ctrlDownAction);
* Action for moving focus emphasis up or down
class CtrlUpDownAction extends AbstractAction
     private boolean m_isUp = true;
     /** Ctor controlling direction of focus emphasis
      * @param name of the action
      * @param isUp - true if dirction of action is up, else false
     public CtrlUpDownAction(String name, boolean isUp)
          super(name);
          m_isUp = isUp;
     /** Moves the focus emphasis
      * @param actionEvent - see javax.swing.AbstractAction class for details
     public void actionPerformed(ActionEvent actionEvent)
          JTable table = (JTable) actionEvent.getSource();
          ListSelectionModel selectModel = table.getSelectionModel();
          int nextRowIndex =
               getNextRowIndex(table.getRowCount(), selectModel.getAnchorSelectionIndex());
          if (selectModel.isSelectedIndex(nextRowIndex))
               selectModel.addSelectionInterval(nextRowIndex, nextRowIndex);
          else
               selectModel.removeSelectionInterval(nextRowIndex, nextRowIndex);
     /** Gets the index of the next row depending on direction up or down
      * @param rowCount - number of rows in the table
      * @param currentRowIndex - index of the row that has focus emphasis
      * @return the index of the next row
     private int getNextRowIndex(int rowCount, int currentRowIndex)
          int nextRowIndex = -1;
          if (m_isUp && currentRowIndex > 0)
               // emphasis moving up one row
               nextRowIndex = currentRowIndex - 1;
          else if (!m_isUp && currentRowIndex < (rowCount - 1))
               // emphasis moving down one row
               nextRowIndex = currentRowIndex + 1;
          return nextRowIndex;
/** Draws a dashed line (well more of a dotted line)
* Used for eg drawing focus emphasis rectangle
* Class draws a rectangle of chosen colour overlaid with a dashed white line.
class DashedLineBorder extends LineBorder
     private BasicStroke m_lineStroke = new BasicStroke();
     private BasicStroke m_dashStroke =
          new BasicStroke(
               m_lineStroke.getLineWidth(),
               BasicStroke.CAP_BUTT,//m_lineStroke.getEndCap(),
               m_lineStroke.getLineJoin(),
               m_lineStroke.getMiterLimit(),
               new float[] { 1,1,1 },
               0);
      * Constructor for DashedLineBorder.
      * @param color
     public DashedLineBorder(Color color)
          super(color);
      * Constructor for DashedLineBorder.
      * @param color
      * @param thickness
     public DashedLineBorder(Color color, int thickness)
          super(color, thickness);
      * Constructor for DashedLineBorder.
      * @param color
      * @param thickness
      * @param roundedCorners
     public DashedLineBorder(Color color, int thickness, boolean roundedCorners)
          super(color, thickness, roundedCorners);
     /** Similar to LineBorder's method but draws a line in the chosen colour
      * before drawing a white dashed line on top of it
      * @see javax.swing.border.Border#paintBorder(Component, Graphics, int, int, int, int)
     public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
          Color oldColor = g.getColor();
          int i;
          Graphics2D g2 = (Graphics2D) g;
          g2.setStroke(m_lineStroke);
          g.setColor(lineColor);
          drawRect(g, x, y, width, height);
          g2.setStroke(m_dashStroke);
          g.setColor(Color.WHITE);
          drawRect(g, x, y, width, height);
          g.setColor(oldColor);
      * @see javax.swing.border.Border#paintBorder(Component, Graphics, int, int, int, int)
     private void drawRect(Graphics g, int x, int y, int width, int height)
          // extracted from Java LineBorder.paintBorder
          int i;
          /// PENDING(klobad) How/should do we support Roundtangles?
          for (i = 0; i < thickness; i++)
               if (!roundedCorners)
                    g.drawRect(x + i, y + i, width - i - i - 1, height - i - i - 1);
               else
                    g.drawRoundRect(
                         x + i,
                         y + i,
                         width - i - i - 1,
                         height - i - i - 1,
                         thickness,
                         thickness);
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.ImageProducer;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.RootPaneContainer;
* Provides static utility methods for JFrames.
public final class FrameUtil {
    * No instances allowed. Just use the static methods.
   private FrameUtil() {
      super();
    * Sets the button that is "activated" when the escape key is used.
    * A bit like
    * SwingUtilities.getRootPane(this).setDefaultButton(myButton);
    * @param jFrame The JFrame or JDialog for which the escape key button should be set.
    * @param button The button which should be clicked automatically when the escape key is pressed.
   public static void setEscapeKeyButton(final RootPaneContainer jFrame, final JButton button) {
      addEscapeKeyAction(jFrame, new AbstractAction() {
         public void actionPerformed(final ActionEvent evt) {
            button.doClick();
    * Adds an action to the jframe's  action map that is triggered by the Escape key.
    * (If you just want to simulate a button click when the escape key is pressed then
    * use setEscapeKeyButton.)
    * A bit like
    * SwingUtilities.getRootPane(this).setDefaultButton(myButton);
    * @param jFrame The JFrame or JDialog for which the escape key action should be set.
    * @param action The action that is executred when the escape key us pressed,
   public static void addEscapeKeyAction(final RootPaneContainer jFrame, final Action action) {
      String actionKey = "escapeAction";
      KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
      // using getRootPane rather than getContentPane, content pane doesn't work in all
      // scenarios
      InputMap inputMap = (jFrame.getRootPane()).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
      inputMap.put(escape, actionKey);
      ActionMap actionMap = (jFrame.getRootPane()).getActionMap();
      actionMap.put(actionKey, action);
    * Finds the escape action for the given frame or dialog if one was added
    * @param jFrame The JFrame or JDialog for which the escape key action should be set.
   public static Action getEscapeKeyAction(final RootPaneContainer jFrame)
      InputMap inputMap = (jFrame.getRootPane()).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
      KeyStroke escapeKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
      ActionMap actionMap = (jFrame.getRootPane()).getActionMap();
      Object actionKey = inputMap.get(escapeKeyStroke);
      Action escapeAction = null;
      if(actionKey != null)
         escapeAction = actionMap.get(actionKey);
      return escapeAction;

From one of the MS windows books.....Going by the books, eh?
Well, apparently MS doesn't do so with Excel... Pressing space will simply trigger an edit!
q1) JTable should have space bar handling out of the box?
(space, CTRL+space, shift+space)
I have not seen this raised as a bug.A bug, no... a feature, maybe. Anyway, JTable provides most of the features needed for creating a table -- it's far from perfect..... adding support for CTRL+SPACE and SHIFT+SPACE is not all that hard to do.
q2) Should the enter key put an editable cell under edit and
q3) if not should the first enter key stop cell editing and a second press activate the default buttonIMHO, a good answer to your question can be found by running MS Excel and see how it's done.
The escape key will cancel editing of a cell that is under edit.and q4, q5
It should, as in Excel. But then, in Lotus 1-2-3, first escape will clear the edit buffer (unless it's empty) and the second escape will cancel editing. Who'is more programmatically correct (I don't know)?
;o)
V.V.

Similar Messages

  • Mapping of JTable Rows and columns and paint it to the JPanel

    Hi,
    I am using JTable and graphics object to draw the JTable on JPanel. But due to some lack of measurement I am not able to draw table cells correctly.
    Apart from this on changing the fontSize I have to redraw it according to the requirement. But when the data size increases it draws absurdly.
    I am using jTable.getCellRect() api to get the row width and height. Please help to redraw a JTable cell row and height on JPanel.
    I am also attaching a sample code with this mail.
    Thanks,
    Ajay
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.*;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import javax.swing.table.*;
    import java.util.*;
    import java.awt.*;
    public class SimpleTableDemo extends JPanel {
        private boolean DEBUG = false;
           private int spacing = 6;
           private Map columnSizes = new HashMap();
           String[] columnNames = {"First Name",
                                    "Last Name",
                                    "Sport",
                                    "# of Years",
                                    "Vegetarian"};
            Object[][] data = {
             {"Kathy", "Smith",
              "SnowboardingXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new Integer(5), new Boolean(false)},
             {"John", "Doe",
              "Rowing", new Integer(3), new Boolean(true)},
             {"Sue", "Black",
              "Knitting", new Integer(2), new Boolean(false)},
             {"Jane", "White",
              "Speed reading", new Integer(20), new Boolean(true)},
             {"Joe", "Brown",
              "Pool", new Integer(10), new Boolean(false)}
            final JTable table = new JTable(data, columnNames);
              Panel1 panel;
        public SimpleTableDemo() {
            super(new GridLayout(3,0));
            table.setPreferredScrollableViewportSize(new Dimension(500, 70));
            //table.setFillsViewportHeight(true);
            if (DEBUG) {
                table.addMouseListener(new MouseAdapter() {
                    public void mouseClicked(MouseEvent e) {
                        printDebugData(table);
            //Create the scroll pane and add the table to it.
            JScrollPane scrollPane = new JScrollPane(table);
            //Add the scroll pane to this panel.
            add(scrollPane);
            panel = new Panel1();
            Rectangle rect = table.getCellRect(0,0,true);
              panel.setX(table.getWidth());
              panel.setY(0);
            panel.setWidth(rect.width);
              panel.setHeight(rect.height);
            panel.setStr(table.getModel().getValueAt(0,0).toString());
              panel.setModel(table);
              add(panel);
            final JComboBox jNumberComboBoxSize = new JComboBox();
              jNumberComboBoxSize.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "11", "12", "14", "16", "18", "20", "24", "30", "36", "48", "72" }));
            jNumberComboBoxSize.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                   jNumberComboBoxSizeActionPerformed(jNumberComboBoxSize);
              JPanel panel2 = new JPanel();
              panel2.add(jNumberComboBoxSize);
              add(panel2);
              adjustColumns();
         private void jNumberComboBoxSizeActionPerformed(JComboBox jNumberComboBoxSize)
            int fontSize = Integer.parseInt(jNumberComboBoxSize.getSelectedItem().toString());
              table.setRowHeight(fontSize);
              table.setFont(new Font("Serif", Font.BOLD, fontSize));
              Rectangle rect = table.getCellRect(0,0,true);
              panel.setX(0);
              panel.setY(0);
           // panel.setWidth(rect.width);
              panel.setHeight(rect.height);
            panel.setStr(table.getModel().getValueAt(0,0).toString());
              panel.setModel(table);
              panel.repaint();
              table.revalidate();
        private void printDebugData(JTable table) {
            int numRows = table.getRowCount();
            int numCols = table.getColumnCount();
            javax.swing.table.TableModel model = table.getModel();
            System.out.println("Value of data: ");
            for (int i=0; i < numRows; i++) {
                System.out.print("    row " + i + ":");
                for (int j=0; j < numCols; j++) {
                    System.out.print("  " + model.getValueAt(i, j));
                System.out.println();
            System.out.println("--------------------------");
          *  Adjust the widths of all the columns in the table
         public void adjustColumns()
              TableColumnModel tcm = table.getColumnModel();
              for (int i = 0; i < tcm.getColumnCount(); i++)
                   adjustColumn(i);
          *  Adjust the width of the specified column in the table
         public void adjustColumn(final int column)
              TableColumn tableColumn = table.getColumnModel().getColumn(column);
              if (! tableColumn.getResizable()) return;
              int columnHeaderWidth = getColumnHeaderWidth( column );
              int columnDataWidth   = getColumnDataWidth( column );
              int preferredWidth    = Math.max(columnHeaderWidth, columnDataWidth);
            panel.setWidth(preferredWidth);
              updateTableColumn(column, preferredWidth);
          *  Calculated the width based on the column name
         private int getColumnHeaderWidth(int column)
              TableColumn tableColumn = table.getColumnModel().getColumn(column);
              Object value = tableColumn.getHeaderValue();
              TableCellRenderer renderer = tableColumn.getHeaderRenderer();
              if (renderer == null)
                   renderer = table.getTableHeader().getDefaultRenderer();
              Component c = renderer.getTableCellRendererComponent(table, value, false, false, -1, column);
              return c.getPreferredSize().width;
          *  Calculate the width based on the widest cell renderer for the
          *  given column.
         private int getColumnDataWidth(int column)
              int preferredWidth = 0;
              int maxWidth = table.getColumnModel().getColumn(column).getMaxWidth();
              for (int row = 0; row < table.getRowCount(); row++)
                  preferredWidth = Math.max(preferredWidth, getCellDataWidth(row, column));
                   //  We've exceeded the maximum width, no need to check other rows
                   if (preferredWidth >= maxWidth)
                       break;
              return preferredWidth;
          *  Get the preferred width for the specified cell
         private int getCellDataWidth(int row, int column)
              //  Inovke the renderer for the cell to calculate the preferred width
              TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
              Component c = table.prepareRenderer(cellRenderer, row, column);
              int width = c.getPreferredSize().width + table.getIntercellSpacing().width;
              return width;
          *  Update the TableColumn with the newly calculated width
         private void updateTableColumn(int column, int width)
              final TableColumn tableColumn = table.getColumnModel().getColumn(column);
              if (! tableColumn.getResizable()) return;
              width += spacing;
              //  Don't shrink the column width
              width = Math.max(width, tableColumn.getPreferredWidth());
              columnSizes.put(tableColumn, new Integer(tableColumn.getWidth()));
              table.getTableHeader().setResizingColumn(tableColumn);
              tableColumn.setWidth(width);
         * 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("SimpleTableDemo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //Create and set up the content pane.
            SimpleTableDemo newContentPane = new SimpleTableDemo();
            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();
    class Panel1 extends JPanel
        int x;
         int y;
         int width;
         int height;
         String str;
         JTable model;
        public void setModel(JTable model)
           this.model = model;
         public void setX(int x)
              this.x = x;
        public void setY(int y)
              this.y = y;
         public void setWidth(int w)
              this.width = w;
        public void setHeight(int h)
              this.height = h;
         public void setStr(String s)
              this.str = s;
        public void paint(Graphics g)
             super.paint(g);
              int initX= 0;
              for(int row=0;row < 5; ++row)
                   initX = x;
                   for (int col=0;col < 5;++col)
                        g.drawRect(x,y,width,height);
                        g.drawString(model.getModel().getValueAt(row,col).toString(),x + 10,y + 10);
                        x = x + width;
                x = initX;
                   y = y + height;
    };

    an easy way would be to use setSize()

  • Mouselistner is not working with jtable in the browser

    Hi
    I am having a problem with jTable.
    I added a mouselistener to table header to sort table but when i run that applet from my netbean ide it works fine but when i run that applet in my browser it doesn't work, i have tested, its not even generate mouseclick event .Please help me guys.
    I call this function after calling initComponents() method of JApplet.
    public void setTableAction()
    //set mouselistener to sort table on click of table header
    final JTableHeader head= jTable1.getTableHeader();
    head.addMouseListener(new java.awt.event.MouseAdapter()
    public void mouseClicked(java.awt.event.MouseEvent evt)
    Vector data= ((DefaultTableModel)jTable1.getModel ()).getDataVector();
    sortTable(data, head.columnAtPoint(evt.getPoint()));
    //set action map to change the default action performed for enter key pressed
    InputMap imap = jTable1.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
    KeyStroke tabKey = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
    final Action oldAction= jTable1.getActionMap().get(imap.get(tabKey)); // get map to set enter key.
    imap.put(enterKey, "enter"); // set enter key
    Action newAction = new AbstractAction(){
    public void actionPerformed(ActionEvent e) {
    oldAction.actionPerformed(e);
    JTable table= (JTable)e.getSource();
    table.changeSelection(0,0,false,false);
    if(table.isCellEditable(0,0))
    String sTemp= (String)table.getValueAt(0,0);
    if(sTemp.length()>0) {
    if(bRenewItem)
    retrieveRcodeDetails("",sTemp);
    else
    processRCodeDetails(sTemp, e);
    }else
    table.editCellAt(0,0);
    jTable1.getActionMap().put("enter", newAction);
    jTable1.setPreferredScrollableViewportSize(jTable1.getPreferredSize());
    }

    Hi,
    I also am using the Bépo layout with an encrypted drive and encountered the same problem: the Return key does not work.
    It seems to work fine if you use the fr-bepo-latin9 keymap.
    # /etc/vconsole.conf
    KEYMAP=fr-bepo-latin9
    But I also looked at the files /usr/share/kbd/keymaps/i386/bepo/fr-bepo.map.gz and /usr/share/kbd/keymaps/i386/bepo/fr-bepo-latin9.map.gz (you can open gzipped files in vim directly). fr-bepo-latin9.map.gz defines keycode 28 (Return) but fr-bepo.map.gz does not.
    I modified fr-bepo.map.gz:
    # vim /usr/share/kbd/keymaps/i386/bepo/fr-bepo.map.gz # Append that line : "keycode 28 = Return".
    # mkinitcpio -p linux # Rebuild the initramfs.
    The Return key now works, but the Backspace (14, "Delete") and Shift (54) keys don’t work. I found that both the cf.map.gz (french canadian layout) and fr-bepo-latin9.map.gz files define those keycodes as well as other non-printing keys so I copied the following lines from fr-bepo-latin9.map.gz to fr-bepo.map.gz:
    keycode 1 = Escape Escape
    keycode 14 = Delete Delete
    keycode 15 = Tab Tab
    keycode 28 = Return
    keycode 29 = Control
    keycode 42 = Shift
    keycode 54 = Shift
    keycode 56 = Alt
    keycode 58 = Caps_Lock
    keycode 97 = Control
    It works! Don’t forget to rebuild the initramfs after you change the keymap file.
    # mkinitcpio -p linux
    I will send a message to the kbd and bépo projects mailing lists and report back.

  • How can I change the default process of VK_ENTER in JTable

    Now I have met a requirment to process the "enter" key event in JTable. But it is found that the JTable has a default process on the ENTER key press, and it will select the next row. Even the worse, the default process is invoked before the KeyListener I registered.
    How can I remove that?
    I have tried the follow ways: 1.remove several keys, such as "selectNextRow","selectNextRowExtendSelection", from the actionMap,
    2.invoke processKeyBinding() in the constructor of my subclass of JTable.
    But both lead to failure.
    And I can't find the default process to the VK_ENTER in the java source code. I need help on this.
    BTW, does anyone know how to eliminate the focus traversal between cells. When I press left arrow or right arrow, the focus traverses in the scope of the selected row.

    thanks
    i also found solution for my poblem:
    i have this code:
    jMenuItem jMnItEdit;
    jMnItEdit.setAccelerator( KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ENTER, 0));
    also i had ActionListener bounded to this JMenuItem
    but Ialso had in form JTable and it always grabbed my VK_ENTER event and that menu item wasn't working at all
    but when i overrode that input map for JTable and set
    tableInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "none");
    everything started to work perfectly,
    thanks a lot

  • One model for JTree and JTable

    Hi.
    Is it possible for a JTree and a JTable to share one model?
    Thank you

    Hope u r not using Comonent TreeTable
    If u have Tree & Table different components, just want to have a common model then u can try this,
    It is nothing but default implementation given in DefaultTableModel
    public class MyTreeTableModel extends DefaultTreeModel implements TableModel, Serializable {
    protected Vector dataVector;
    /** List of listeners */
    protected EventListenerList listenerList = new EventListenerList();
    /** The <code>Vector</code> of column identifiers. */
    protected Vector columnIdentifiers;
    public MyTreeTableModel(TreeNode root) {
    this(root, false);
    // constructor for TreeModel only
    public MyTreeTableModel(TreeNode root, boolean asksAllowsChildren) {
    super(root, asksAllowsChildren);
    // constructor for TableModel only
    public MyTreeTableModel() {
    this(0, 0);
    private static Vector newVector(int size) {
    Vector v = new Vector(size);
    v.setSize(size);
    return v;
    // constructor for TableModel only
    public MyTreeTableModel(int rowCount, int columnCount) {
    this(newVector(columnCount), rowCount);
    // constructor for TableModel only
    public MyTreeTableModel(Vector columnNames, int rowCount) {
    super(null);
    setDataVector(newVector(rowCount), columnNames);
    // constructor for TableModel only
    public MyTreeTableModel(Object[] columnNames, int rowCount) {
    this(convertToVector(columnNames), rowCount);
    // constructor for TableModel only
    public MyTreeTableModel(Vector data, Vector columnNames) {
    super(null);
    setDataVector(data, columnNames);
    // constructor for TableModel only
    public MyTreeTableModel(Object[][] data, Object[] columnNames) {
    super(null);
    setDataVector(data, columnNames);
    * Returns a default name for the column using spreadsheet conventions:
    * A, B, C, ... Z, AA, AB, etc. If <code>column</code> cannot be found,
    * returns an empty string.
    * @param column the column being queried
    * @return a string containing the default name of <code>column</code>
    private String getDefaultColumnName(int column) {
    String result = "";
    for (; column >= 0; column = column / 26 - 1) {
    result = (char)((char)(column%26)+'A') + result;
    return result;
    * Returns a column given its name.
    * Implementation is naive so this should be overridden if
    * this method is to be called often. This method is not
    * in the <code>TableModel</code> interface and is not used by the
    * <code>JTable</code>.
    * @param columnName string containing name of column to be located
    * @return the column with <code>columnName</code>, or -1 if not found
    public int findColumn(String columnName) {
    for (int i = 0; i < getColumnCount(); i++) {
    if (columnName.equals(getColumnName(i))) {
    return i;
    return -1;
    * Returns <code>Object.class</code> regardless of <code>columnIndex</code>.
    * @param columnIndex the column being queried
    * @return the Object.class
    public Class getColumnClass(int columnIndex) {
    return Object.class;
    // Managing Listeners
    * Adds a listener to the list that's notified each time a change
    * to the data model occurs.
    * @param     l          the TableModelListener
    public void addTableModelListener(TableModelListener l) {
    listenerList.add(TableModelListener.class, l);
    * Removes a listener from the list that's notified each time a
    * change to the data model occurs.
    * @param     l          the TableModelListener
    public void removeTableModelListener(TableModelListener l) {
    listenerList.remove(TableModelListener.class, l);
    * Returns an array of all the table model listeners
    * registered on this model.
    * @return all of this model's <code>TableModelListener</code>s
    * or an empty
    * array if no table model listeners are currently registered
    public TableModelListener[] getTableModelListeners() {
    return (TableModelListener[])listenerList.getListeners(
    TableModelListener.class);
    // Fire methods
    * Notifies all listeners that all cell values in the table's
    * rows may have changed. The number of rows may also have changed
    * and the <code>JTable</code> should redraw the
    * table from scratch. The structure of the table (as in the order of the
    * columns) is assumed to be the same.
    public void fireTableDataChanged() {
    fireTableChanged(new TableModelEvent(this));
    * Notifies all listeners that the table's structure has changed.
    * The number of columns in the table, and the names and types of
    * the new columns may be different from the previous state.
    * If the <code>JTable</code> receives this event and its
    * <code>autoCreateColumnsFromModel</code>
    * flag is set it discards any table columns that it had and reallocates
    * default columns in the order they appear in the model. This is the
    * same as calling <code>setModel(TableModel)</code> on the
    * <code>JTable</code>.
    public void fireTableStructureChanged() {
    fireTableChanged(new TableModelEvent(this, TableModelEvent.HEADER_ROW));
    * Notifies all listeners that rows in the range
    * <code>[firstRow, lastRow]</code>, inclusive, have been inserted.
    * @param firstRow the first row
    * @param lastRow the last row
    public void fireTableRowsInserted(int firstRow, int lastRow) {
    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
    TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
    * Notifies all listeners that rows in the range
    * <code>[firstRow, lastRow]</code>, inclusive, have been updated.
    * @param firstRow the first row
    * @param lastRow the last row
    public void fireTableRowsUpdated(int firstRow, int lastRow) {
    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
    TableModelEvent.ALL_COLUMNS, TableModelEvent.UPDATE));
    * Notifies all listeners that rows in the range
    * <code>[firstRow, lastRow]</code>, inclusive, have been deleted.
    * @param firstRow the first row
    * @param lastRow the last row
    public void fireTableRowsDeleted(int firstRow, int lastRow) {
    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
    TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE));
    * Notifies all listeners that the value of the cell at
    * <code>[row, column]</code> has been updated.
    * @param row row of cell which has been updated
    * @param column column of cell which has been updated
    public void fireTableCellUpdated(int row, int column) {
    fireTableChanged(new TableModelEvent(this, row, row, column));
    * Forwards the given notification event to all
    * <code>TableModelListeners</code> that registered
    * themselves as listeners for this table model.
    * @param e the event to be forwarded
    public void fireTableChanged(TableModelEvent e) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners==TableModelListener.class) {
    ((TableModelListener)listeners[i+1]).tableChanged(e);
    * Returns an array of all the objects currently registered
    * as <code><em>Foo</em>Listener</code>s
    * upon this <code>AbstractTableModel</code>.
    * <code><em>Foo</em>Listener</code>s are registered using the
    * <code>add<em>Foo</em>Listener</code> method.
    * <p>
    * You can specify the <code>listenerType</code> argument
    * with a class literal,
    * such as
    * <code><em>Foo</em>Listener.class</code>.
    * For example, you can query a
    * model <code>m</code>
    * for its table model listeners with the following code:
    * <pre>TableModelListener[] tmls = (TableModelListener[])(m.getListeners(TableModelListener.class));</pre>
    * If no such listeners exist, this method returns an empty array.
    * @param listenerType the type of listeners requested; this parameter
    * should specify an interface that descends from
    * <code>java.util.EventListener</code>
    * @return an array of all objects registered as
    * <code><em>Foo</em>Listener</code>s on this component,
    * or an empty array if no such
    * listeners have been added
    * @exception ClassCastException if <code>listenerType</code>
    * doesn't specify a class or interface that implements
    * <code>java.util.EventListener</code>
    public EventListener[] getListeners(Class listenerType) {
    return listenerList.getListeners(listenerType);
    * Returns the <code>Vector</code> of <code>Vectors</code>
    * that contains the table's
    * data values. The vectors contained in the outer vector are
    * each a single row of values. In other words, to get to the cell
    * at row 1, column 5: <p>
    * <code>((Vector)getDataVector().elementAt(1)).elementAt(5);</code><p>
    * @return the vector of vectors containing the tables data values
    public Vector getDataVector() {
    return dataVector;
    private static Vector nonNullVector(Vector v) {
    return (v != null) ? v : new Vector();
    * Replaces the current <code>dataVector</code> instance variable
    * with the new Vector of rows, <code>dataVector</code>.
    * <code>columnIdentifiers</code> are the names of the new
    * columns. The first name in <code>columnIdentifiers</code> is
    * mapped to column 0 in <code>dataVector</code>. Each row in
    * <code>dataVector</code> is adjusted to match the number of
    * columns in <code>columnIdentifiers</code>
    * either by truncating the <code>Vector</code> if it is too long,
    * or adding <code>null</code> values if it is too short.
    * <p>Note that passing in a <code>null</code> value for
    * <code>dataVector</code> results in unspecified behavior,
    * an possibly an exception.
    * @param dataVector the new data vector
    * @param columnIdentifiers the names of the columns
    public void setDataVector(Vector dataVector, Vector columnIdentifiers) {
    this.dataVector = nonNullVector(dataVector);
    this.columnIdentifiers = nonNullVector(columnIdentifiers);
    justifyRows(0, getRowCount());
    fireTableStructureChanged();
    * Replaces the value in the <code>dataVector</code> instance
    * variable with the values in the array <code>dataVector</code>.
    * The first index in the <code>Object[][]</code>
    * array is the row index and the second is the column index.
    * <code>columnIdentifiers</code> are the names of the new columns.
    * @param dataVector          the new data vector
    * @param columnIdentifiers     the names of the columns
    public void setDataVector(Object[][] dataVector, Object[] columnIdentifiers) {
    setDataVector(convertToVector(dataVector), convertToVector(columnIdentifiers));
    * Equivalent to <code>fireTableChanged</code>.
    * @param event the change event
    public void newDataAvailable(TableModelEvent event) {
    fireTableChanged(event);
    // Manipulating rows
    private void justifyRows(int from, int to) {
    // Sometimes the MyTreeTableModel is subclassed
    // instead of the AbstractTableModel by mistake.
    // Set the number of rows for the case when getRowCount
    // is overridden.
    dataVector.setSize(getRowCount());
    for (int i = from; i < to; i++) {
    if (dataVector.elementAt(i) == null) {
    dataVector.setElementAt(new Vector(), i);
    ((Vector)dataVector.elementAt(i)).setSize(getColumnCount());
    * Ensures that the new rows have the correct number of columns.
    * This is accomplished by using the <code>setSize</code> method in
    * <code>Vector</code> which truncates vectors
    * which are too long, and appends <code>null</code>s if they
    * are too short.
    * This method also sends out a <code>tableChanged</code>
    * notification message to all the listeners.
    * @param e this <code>TableModelEvent</code> describes
    * where the rows were added.
    *                    If <code>null</code> it assumes
    * all the rows were newly added
    public void newRowsAdded(TableModelEvent e) {
    justifyRows(e.getFirstRow(), e.getLastRow() + 1);
    fireTableChanged(e);
    * Equivalent to <code>fireTableChanged</code>.
    * @param event the change event
    public void rowsRemoved(TableModelEvent event) {
    fireTableChanged(event);
    * Obsolete as of Java 2 platform v1.3. Please use <code>setRowCount</code> instead.
    * Sets the number of rows in the model. If the new size is greater
    * than the current size, new rows are added to the end of the model
    * If the new size is less than the current size, all
    * rows at index <code>rowCount</code> and greater are discarded. <p>
    * @param rowCount the new number of rows
    public void setNumRows(int rowCount) {
    int old = getRowCount();
    if (old == rowCount) {
    return;
    dataVector.setSize(rowCount);
    if (rowCount <= old) {
    fireTableRowsDeleted(rowCount, old-1);
    else {
    justifyRows(old, rowCount);
    fireTableRowsInserted(old, rowCount-1);
    * Sets the number of rows in the model. If the new size is greater
    * than the current size, new rows are added to the end of the model
    * If the new size is less than the current size, all
    * rows at index <code>rowCount</code> and greater are discarded. <p>
    public void setRowCount(int rowCount) {
    setNumRows(rowCount);
    * Adds a row to the end of the model. The new row will contain
    * <code>null</code> values unless <code>rowData</code> is specified.
    * Notification of the row being added will be generated.
    * @param rowData optional data of the row being added
    public void addRow(Vector rowData) {
    insertRow(getRowCount(), rowData);
    * Adds a row to the end of the model. The new row will contain
    * <code>null</code> values unless <code>rowData</code> is specified.
    * Notification of the row being added will be generated.
    * @param rowData optional data of the row being added
    public void addRow(Object[] rowData) {
    addRow(convertToVector(rowData));
    * Inserts a row at <code>row</code> in the model. The new row
    * will contain <code>null</code> values unless <code>rowData</code>
    * is specified. Notification of the row being added will be generated.
    * @param row the row index of the row to be inserted
    * @param rowData optional data of the row being added
    * @exception ArrayIndexOutOfBoundsException if the row was invalid
    public void insertRow(int row, Vector rowData) {
    dataVector.insertElementAt(rowData, row);
    justifyRows(row, row+1);
    fireTableRowsInserted(row, row);
    * Inserts a row at <code>row</code> in the model. The new row
    * will contain <code>null</code> values unless <code>rowData</code>
    * is specified. Notification of the row being added will be generated.
    * @param row the row index of the row to be inserted
    * @param rowData optional data of the row being added
    * @exception ArrayIndexOutOfBoundsException if the row was invalid
    public void insertRow(int row, Object[] rowData) {
    insertRow(row, convertToVector(rowData));
    private static int gcd(int i, int j) {
    return (j == 0) ? i : gcd(j, i%j);
    private static void rotate(Vector v, int a, int b, int shift) {
    int size = b - a;
    int r = size - shift;
    int g = gcd(size, r);
    for(int i = 0; i < g; i++) {
    int to = i;
    Object tmp = v.elementAt(a + to);
    for(int from = (to + r) % size; from != i; from = (to + r) % size) {
    v.setElementAt(v.elementAt(a + from), a + to);
    to = from;
    v.setElementAt(tmp, a + to);
    * Moves one or more rows from the inlcusive range <code>start</code> to
    * <code>end</code> to the <code>to</code> position in the model.
    * After the move, the row that was at index <code>start</code>
    * will be at index <code>to</code>.
    * This method will send a <code>tableChanged</code> notification
    * message to all the listeners. <p>
    * <pre>
    * Examples of moves:
    * <p>
    * 1. moveRow(1,3,5);
    * a|B|C|D|e|f|g|h|i|j|k - before
    * a|e|f|g|h|B|C|D|i|j|k - after
    * <p>
    * 2. moveRow(6,7,1);
    * a|b|c|d|e|f|G|H|i|j|k - before
    * a|G|H|b|c|d|e|f|i|j|k - after
    * <p>
    * </pre>
    * @param start the starting row index to be moved
    * @param end the ending row index to be moved
    * @param to the destination of the rows to be moved
    * @exception ArrayIndexOutOfBoundsException if any of the elements
    * would be moved out of the table's range
    public void moveRow(int start, int end, int to) {
    int shift = to - start;
    int first, last;
    if (shift < 0) {
    first = to;
    last = end;
    else {
    first = start;
    last = to + end - start;
    rotate(dataVector, first, last + 1, shift);
    fireTableRowsUpdated(first, last);
    * Removes the row at <code>row</code> from the model. Notification
    * of the row being removed will be sent to all the listeners.
    * @param row the row index of the row to be removed
    * @exception ArrayIndexOutOfBoundsException if the row was invalid
    public void removeRow(int row) {
    dataVector.removeElementAt(row);
    fireTableRowsDeleted(row, row);
    // Manipulating columns
    * Replaces the column identifiers in the model. If the number of
    * <code>newIdentifier</code>s is greater than the current number
    * of columns, new columns are added to the end of each row in the model.
    * If the number of <code>newIdentifier</code>s is less than the current
    * number of columns, all the extra columns at the end of a row are
    * discarded. <p>
    * @param newIdentifiers vector of column identifiers. If
    *                    <code>null</code>, set the model
    * to zero columns
    public void setColumnIdentifiers(Vector columnIdentifiers) {
    setDataVector(dataVector, columnIdentifiers);
    * Replaces the column identifiers in the model. If the number of
    * <code>newIdentifier</code>s is greater than the current number
    * of columns, new columns are added to the end of each row in the model.
    * If the number of <code>newIdentifier</code>s is less than the current
    * number of columns, all the extra columns at the end of a row are
    * discarded. <p>
    * @param newIdentifiers array of column identifiers.
    *                    If <code>null</code>, set
    * the model to zero columns
    public void setColumnIdentifiers(Object[] newIdentifiers) {
    setColumnIdentifiers(convertToVector(newIdentifiers));
    * Sets the number of columns in the model. If the new size is greater
    * than the current size, new columns are added to the end of the model
    * with <code>null</code> cell values.
    * If the new size is less than the current size, all columns at index
    * <code>columnCount</code> and greater are discarded.
    * @param columnCount the new number of columns in the model
    public void setColumnCount(int columnCount) {
    columnIdentifiers.setSize(columnCount);
    justifyRows(0, getRowCount());
    fireTableStructureChanged();
    * Adds a column to the model. The new column will have the
    * identifier <code>columnName</code>, which may be null. This method
    * will send a
    * <code>tableChanged</code> notification message to all the listeners.
    * This method is a cover for <code>addColumn(Object, Vector)</code> which
    * uses <code>null</code> as the data vector.
    * @param columnName the identifier of the column being added
    public void addColumn(Object columnName) {
    addColumn(columnName, (Vector)null);
    * Adds a column to the model. The new column will have the
    * identifier <code>columnName</code>, which may be null.
    * <code>columnData</code> is the
    * optional vector of data for the column. If it is <code>null</code>
    * the column is filled with <code>null</code> values. Otherwise,
    * the new data will be added to model starting with the first
    * element going to row 0, etc. This method will send a
    * <code>tableChanged</code> notification message to all the listeners.
    * @param columnName the identifier of the column being added
    * @param columnData optional data of the column being added
    public void addColumn(Object columnName, Vector columnData) {
    columnIdentifiers.addElement(columnName);
    if (columnData != null) {
    int columnSize = columnData.size();
    if (columnSize > getRowCount()) {
    dataVector.setSize(columnSize);
    justifyRows(0, getRowCount());
    int newColumn = getColumnCount() - 1;
    for(int i = 0; i < columnSize; i++) {
    Vector row = (Vector)dataVector.elementAt(i);
    row.setElementAt(columnData.elementAt(i), newColumn);
    else {
    justifyRows(0, getRowCount());
    fireTableStructureChanged();
    * Adds a column to the model. The new column will have the
    * identifier <code>columnName</code>. <code>columnData</code> is the
    * optional array of data for the column. If it is <code>null</code>
    * the column is filled with <code>null</code> values. Otherwise,
    * the new data will be added to model starting with the first
    * element going to row 0, etc. This method will send a
    * <code>tableChanged</code> notification message to all the listeners.
    public void addColumn(Object columnName, Object[] columnData) {
    addColumn(columnName, convertToVector(columnData));
    // Implementing the TableModel interface
    * Returns the number of rows in this data table.
    * @return the number of rows in the model
    public int getRowCount() {
    return dataVector.size();
    * Returns the number of columns in this data table.
    * @return the number of columns in the model
    public int getColumnCount() {
    return columnIdentifiers.size();
    * Returns the column name.
    * @return a name for this column using the string value of the
    * appropriate member in <code>columnIdentifiers</code>.
    * If <code>columnIdentifiers</code> does not have an entry
    * for this index, returns the default
    * name provided by the superclass
    public String getColumnName(int column) {
    Object id = null;
    // This test is to cover the case when
    // getColumnCount has been subclassed by mistake ...
    if (column < columnIdentifiers.size()) {
    id = columnIdentifiers.elementAt(column);
    return (id == null) ? getDefaultColumnName(column)
    : id.toString();
    * Returns true regardless of parameter values.
    * @param row the row whose value is to be queried
    * @param column the column whose value is to be queried
    * @return true
    public boolean isCellEditable(int row, int column) {
    return true;
    * Returns an attribute value for the cell at <code>row</code>
    * and <code>column</code>.
    * @param row the row whose value is to be queried
    * @param column the column whose value is to be queried
    * @return the value Object at the specified cell
    * @exception ArrayIndexOutOfBoundsException if an invalid row or
    * column was given
    public Object getValueAt(int row, int column) {
    Vector rowVector = (Vector)dataVector.elementAt(row);
    return rowVector.elementAt(column);
    * Sets the object value for the cell at <code>column</code> and
    * <code>row</code>. <code>aValue</code> is the new value. This method
    * will generate a <code>tableChanged</code> notification.
    * @param aValue the new value; this can be null
    * @param row the row whose value is to be changed
    * @param column the column whose value is to be changed
    * @exception ArrayIndexOutOfBoundsException if an invalid row or
    * column was given
    public void setValueAt(Object aValue, int row, int column) {
    Vector rowVector = (Vector)dataVector.elementAt(row);
    rowVector.setElementAt(aValue, column);
    fireTableCellUpdated(row, column);
    // Protected Methods
    * Returns a vector that contains the same objects as the array.
    * @param anArray the array to be converted
    * @return the new vector; if <code>anArray</code> is <code>null</code>,
    *                    returns <code>null</code>
    protected static Vector convertToVector(Object[] anArray) {
    if (anArray == null) {
    return null;
    Vector v = new Vector(anArray.length);
    for (int i=0; i < anArray.length; i++) {
    v.addElement(anArray[i]);
    return v;
    * Returns a vector of vectors that contains the same objects as the array.
    * @param anArray the double array to be converted
    * @return the new vector of vectors; if <code>anArray</code> is
    *                    <code>null</code>, returns <code>null</code>
    protected static Vector convertToVector(Object[][] anArray) {
    if (anArray == null) {
    return null;
    Vector v = new Vector(anArray.length);
    for (int i=0; i < anArray.length; i++) {
    v.addElement(convertToVector(anArray[i]));
    return v;

  • JTable displays string in wrong order : my code problem or Java problem ?

    I have the following code that displays data in a JTable, most of the time it works fine, but I've realized when I have a cell with values like : "Snowboarding"+"[123456789]"
    It would display it as : [Snowboarding[123456789
    For a string like : "Chasing toddlers"+"<123456789>"
    It would display it as : <Chasing toddlers<123456789
    It not only moved the last bracket to the front, but also changed its direction from "]" to "[" and from ">" to "<"
    Is there anything wrong with my code ? Or is this a Java problem ?
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.table.*;
    import java.io.*;
    import java.sql.*;
    import java.util.*;
    import java.util.List;
    import javax.swing.event.TableModelEvent;
    import javax.swing.event.TableModelListener;
    public class Table_Panel extends JPanel implements ItemListener
      public static final long serialVersionUID=26362862L;
      static final int Row_Color_Style_Default=-1,Row_Color_Style_None=0,Row_Color_Style_Blue_Gray=1,Row_Color_Style_Cyan_Gray=2,Row_Color_Style_Blue=3,
                       Row_Color_Style_Gray=4,Row_Color_Style_Red_Green=5,Row_Color_Style_Green_Yellow=6,Row_Color_Style_Red_Yellow=7,
                       Max_Header_Cell_Width=0,Header_Width=1,Cell_Width=2;
      static int Row_Color_Style=Row_Color_Style_Cyan_Gray,Preffered_Width=Header_Width;
    //  static int Row_Color_Style=Row_Color_Style_None,Preffered_Width=Header_Width;
    //boolean        Debug=true,
      boolean        Debug=false,
    //               Use_Row_Colors=true,
                     Use_Row_Colors=false;
      JFrame Table_Frame;
      TableModel My_Model;
      JScrollPane scrollPane=new JScrollPane();
      public JTable Table;
      static String columnNames[],Default_Delimiter=\",\";
      Object[][] data;
      static Dimension Screen_Size=Toolkit.getDefaultToolkit().getScreenSize();
      int Column_Width[];
      static Color Default_Selection_Color=new Color(250,135,200);
      Color Selection_Color=Default_Selection_Color;
      public Table_Panel(ResultSet RS,String Table_Name,boolean Show_External_Table,int Row_Color_Style,int Preffered_Width,boolean In_Original_Order)
        String Value,Table_Column_Names[]=null;
        Object[][] Table_Data=null;
        int Row_Count,Index=0;
        try
          if (RS==null) return;
          else
            RS.last();
            Row_Count=RS.getRow();
            RS.beforeFirst();
          ResultSetMetaData rsmd=RS.getMetaData();
          int Column_Count=rsmd.getColumnCount();
          Table_Column_Names=new String[Column_Count];
          Table_Data=new Object[Row_Count][Column_Count];
          for (int i=1;i<=Column_Count;i++) Table_Column_Names[i-1]=rsmd.getColumnLabel(i);            // Get column names
    //Out("Row_Count="+Row_Count+"  Column_Count="+Column_Count);
          while (RS.next())                                                                            // Get all rows
            for (int i=1;i<=Column_Count;i++)
              Value=RS.getString(i);
              Table_Data[Index][i-1]=(Value==null)?"null":Value;
            Index++;
    //      if (Test_Ct++>300) break;
        catch (Exception e) { e.printStackTrace(); }
        scrollPane=new Table_Panel(Table_Name,Table_Column_Names,Table_Data,Table_Data.length,false,Show_External_Table,false,Row_Color_Style,Preffered_Width,Selection_Color,In_Original_Order).scrollPane;
      public Table_Panel(String[] Table_Column_Names,Object[][] Table_Data,Color Selection_Color,boolean In_Original_Order)
        this("",Table_Column_Names,Table_Data,Table_Data.length,false,false,false,Row_Color_Style,Preffered_Width,Selection_Color,In_Original_Order);
      public Table_Panel(String Table_Name,String[] Table_Column_Names,Object[][] Table_Data,boolean Show_External_Table,Color Selection_Color,boolean In_Original_Order)
        this(Table_Name,Table_Column_Names,Table_Data,Table_Data.length,false,Show_External_Table,false,Row_Color_Style,Preffered_Width,Selection_Color,In_Original_Order);
      public Table_Panel(String Table_Name,String[] Table_Column_Names,Object[][] Table_Data,int Row_Count,boolean Is_Child,boolean Show_External_Table,boolean Manage_Attachment,int Row_Color_Style,int Preffered_Width,Color Selection_Color,boolean In_Original_Order)
        columnNames=Table_Column_Names;
        if (In_Original_Order) data=Table_Data;
        else
          data=new Object[Table_Data.length][columnNames.length];
          for (int row=0;row<Table_Data.length;row++)
            data[row]=new Object[columnNames.length];
            for (int Column=0;Column<Table_Data[row].length;Column++) data[row][Column]=Table_Data[Table_Data.length-1-row][Column];
        Column_Width=new int[columnNames.length];
        this.Row_Color_Style=Row_Color_Style;
        Use_Row_Colors=(Row_Color_Style!=Row_Color_Style_None);
        this.Preffered_Width=Preffered_Width;
        if (Selection_Color!=null) this.Selection_Color=Selection_Color;
    //    Out("this.Selection_Color="+this.Selection_Color);
    //    TableModel My_Model=new DefaultTableModel(Table_Data,columnNames)
        TableModel My_Model=new DefaultTableModel(data,columnNames)
          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)
    //      Out(row+","+col+"["+data[row][col]+"]   data.length="+data.length+"  data[0].length="+data[0].length);
            return (data[row][col]==null)?"":((data[row][col] instanceof Boolean)?data[row][col]:data[row][col].toString()); // Non-boolean values will have bgcolor
          public Class getColumnClass(int column)
            Class returnValue;
            if ((column>=0) && (column<getColumnCount())) returnValue=getValueAt(0,column).getClass();
            else returnValue=Object.class;
            return returnValue;
        // 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<0) 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)
            String Execution_Dir=getClass().getProtectionDomain().getCodeSource().getLocation().toString();
            if (Debug) System.out.println("Execution_Dir="+Execution_Dir+"\nLast_Value="+Table_Grid_Cell_Renderer.Last_Value+"  Setting value at [ "+row+","+col+" ] to "+value+" (an instance of "+value.getClass()+")");
            if (Execution_Dir.toLowerCase().indexOf("c:/")!=-1 || value.getClass()==Boolean.class || !Use_Row_Colors) data[row][col]=value;
    //     else data[row][col]=(Table_Grid_CellRenderer.Last_Value==null)?value:value.toString().substring(Table_Grid_CellRenderer.Last_Value.toString().length());
            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("--------------------------------------------------------------------------");
        TableSorter sorter=new TableSorter(My_Model);
        Table=new JTable(sorter)
    //    Table=new JTable(My_Model)
          public static final long serialVersionUID=26362862L;
          public String getToolTipText(MouseEvent e)           // Implement table cell tool tips.
            Object Cell_Tip;
            String tip=null;
            java.awt.Point p=e.getPoint();
            int rowIndex=rowAtPoint(p);
            int colIndex=columnAtPoint(p);
            int realColumnIndex=convertColumnIndexToModel(colIndex);
            Cell_Tip=getValueAt(rowIndex,colIndex);
    //        if (realColumnIndex == 2)                         //Sport column
              tip=Cell_Tip.toString();
            else if (realColumnIndex == 4)                      //Veggie column
              TableModel model=getModel();
              String firstName=(String)model.getValueAt(rowIndex,0);
              String lastName=(String)model.getValueAt(rowIndex,1);
              Boolean veggie=(Boolean)model.getValueAt(rowIndex,4);
              if (Boolean.TRUE.equals(veggie)) tip=firstName+" "+lastName+" is a vegetarian";
              else tip=firstName+" "+lastName+" is not a vegetarian";
            else
              // You can omit this part if you know you don't have any renderers that supply their own tool tips.
              tip=super.getToolTipText(e);
            return tip;
    //    RowSorter<TableModel> sorter=new TableRowSorter<TableModel>(My_Model);
    //    Table.setRowSorter(sorter);
        Table.setSelectionBackground(this.Selection_Color);
        int Table_Height=Table.getRowHeight()*Row_Count;
        // sorter.addMouseListenerToHeaderInTable(Table);      // ADDED THIS
        sorter.setTableHeader(Table.getTableHeader());
        if (Table_Column_Names.length>20) Table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        if (Manage_Attachment) Table.setPreferredScrollableViewportSize(new Dimension(500,(Table_Height>850)?850:Table_Height));
        else Table.setPreferredScrollableViewportSize(new Dimension(1000,(Table_Height>850)?850:Table_Height));
        if (Use_Row_Colors) Table.setDefaultRenderer(Object.class,new Table_Grid_Cell_Renderer());
        //Create the scroll pane and add the table to it.
        scrollPane=new JScrollPane(Table);
        //Set up column sizes.
        initColumnSizes(Table,My_Model);
        //Add the scroll pane to this window.
        if (Show_External_Table)
          Table_Frame=new JFrame(Table_Name);
          Table_Frame.getContentPane().add(scrollPane);
          Table_Frame.addWindowListener(new WindowAdapter()
            public void windowActivated(WindowEvent e) { }
            public void windowClosed(WindowEvent e) { }
            public void windowClosing(WindowEvent e)  { System.exit(0); }
            public void windowDeactivated(WindowEvent e)  { }
            public void windowDeiconified(WindowEvent e)  { scrollPane.repaint(); }
            public void windowGainedFocus(WindowEvent e)  { scrollPane.repaint(); }
            public void windowIconified(WindowEvent e)  { }
            public void windowLostFocus(WindowEvent e)  { }
            public void windowOpening(WindowEvent e) { scrollPane.repaint(); }
            public void windowOpened(WindowEvent e)  { }
            public void windowResized(WindowEvent e) { scrollPane.repaint(); } 
            public void windowStateChanged(WindowEvent e) { scrollPane.repaint(); }
          Table_Frame.pack();
          Table_Frame.setBounds((Screen_Size.width-Table_Frame.getWidth())/2,(Screen_Size.height-Table_Frame.getHeight())/2,Table_Frame.getWidth(),Table_Frame.getHeight());
          Table_Frame.setVisible(true);
          if (Is_Child) Table_Frame.addComponentListener(new ComponentAdapter() { public void componentClosing(ComponentEvent e) { System.exit(0); } });
        else add(scrollPane);
      public Table_Panel(String File_Name) { this(File_Name,false,Row_Color_Style_Cyan_Gray,Preffered_Width,null,Default_Selection_Color,true); }
      public Table_Panel(String File_Name,int Row_Color_Style,boolean In_Original_Order) { this(File_Name,false,Row_Color_Style,Preffered_Width,null,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,String Delimiter,boolean In_Original_Order) { this(File_Name,false,Row_Color_Style_Cyan_Gray,Preffered_Width,Delimiter,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,int Preffered_Width,String Delimiter,boolean In_Original_Order) { this(File_Name,false,Row_Color_Style,Preffered_Width,Delimiter,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,int Row_Color_Style,int Preffered_Width,String Delimiter,boolean In_Original_Order) { this(File_Name,false,Row_Color_Style,Preffered_Width,Delimiter,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,boolean Show_External_Table,boolean In_Original_Order) { this(File_Name,Show_External_Table,Row_Color_Style,Preffered_Width,null,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,boolean Show_External_Table,String Delimiter,boolean In_Original_Order) { this(File_Name,Show_External_Table,Row_Color_Style,Preffered_Width,Delimiter,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,boolean Show_External_Table,int Row_Color_Style,int Preffered_Width,String Delimiter,Color Selection_Color,boolean In_Original_Order)
        String Table_Column_Names[],Column_Name_Line="";
        int Row_Count=0,Index=0;
        boolean Is_Child=false,Manage_Attachment=false;
        StringTokenizer ST;
        if (Delimiter==null) Delimiter=Default_Delimiter;
        if (new File(File_Name).exists())
          try
            String Line,Str=Tool_Lib.Read_File(File_Name).toString();
            ST=new StringTokenizer(Str,"\n");
            Line=ST.nextToken();
            Row_Count=ST.countTokens();
            Object[][] Table_Data=new Object[Row_Count][];
            if (Delimiter.equals(" ")) Line=Line.replaceAll(" {2,}"," ").trim();     // Replace multiple spaces with the delimiter space
            Table_Column_Names=Line.split(Delimiter);
            columnNames=Table_Column_Names;
            for (int i=0;i<Table_Column_Names.length;i++) Column_Name_Line+=Table_Column_Names[i]+"  ";
    //Out("Column_Name_Line [ "+Table_Column_Names.length+" ]="+Column_Name_Line);
            while (ST.hasMoreTokens())
              Line=ST.nextToken();
    //Out(Line);
              if (Delimiter.equals(" ")) Line=Line.replaceAll(" {2,}"," ").trim();   // Replace multiple spaces with the delimiter space
              if (Line.indexOf(Delimiter)!=-1) Table_Data[Index]=Line.split(Delimiter);
              else
                Table_Data[Index]=new Object[Table_Column_Names.length];
                Table_Data[Index][0]=Line;
                for (int i=1;i<Table_Column_Names.length;i++) Table_Data[Index]="";
    Index++;
    Line="";
    for (int i=0;i<Table_Data.length;i++)
    Line+="[ "+Table_Data[i].length+" ] ";
    for (int j=0;j<Table_Data[i].length;j++) Line+=Table_Data[i][j]+" ";
    Line+="\n";
    Out(Line);
    Table_Panel A_Table_Panel=new Table_Panel(File_Name,Table_Column_Names,Table_Data,Row_Count,Is_Child,Show_External_Table,Manage_Attachment,Row_Color_Style,Preffered_Width,Selection_Color,In_Original_Order);
    Table=A_Table_Panel.Table;
    scrollPane=A_Table_Panel.scrollPane;
    Column_Width=A_Table_Panel.Column_Width;
    data=A_Table_Panel.data;
    catch (Exception e) { e.printStackTrace(); }
    public void setPreferredSize(Dimension A_Dimension) { scrollPane.setPreferredSize(A_Dimension); }
    // 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().
    void initColumnSizes(JTable table,TableModel model)
    TableColumn column=null;
    Component comp=null;
    int headerWidth=0,cellWidth=0;
    Object[] longValues=(data.length>0)?data[0]:null;
    TableCellRenderer headerRenderer=table.getTableHeader().getDefaultRenderer();
    if (data.length<1) return;
    for (int i=0;i<model.getColumnCount();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;
    switch (Preffered_Width)
    case Max_Header_Cell_Width : column.setPreferredWidth(Math.max(headerWidth,cellWidth));break;
    case Header_Width : column.setPreferredWidth(headerWidth);break;
    case Cell_Width : column.setPreferredWidth(cellWidth);break;
    Column_Width[i]=column.getPreferredWidth();
    if (Debug) Out("Initializing width of column "+i+". "+"headerWidth="+headerWidth+"; cellWidth="+cellWidth+" Column_Width["+i+"]="+Column_Width[i]);
    // Detects a state change in any of the Lists. Resets the variable corresponding to the selected item in a particular List. Invokes changeFont with the currently selected fontname, style and size attributes.
    public void itemStateChanged(ItemEvent e)
    Out(e.toString());
    if (e.getStateChange() != ItemEvent.SELECTED) return;
    Object list=e.getSource();
    public static void Out(String message) { System.out.println(message); }
    // Create the GUI and show it. For thread safety, this method should be invoked from the event-dispatching thread.
    static void Create_And_Show_GUI()
    boolean Demo_External_Table=true;
    // boolean Demo_External_Table=false;
    final Table_Panel demo;
    String[] columnNames={"First Names","Last Names","Sport","Num of Years","Vegetarian"};
    Object[][] data={{"Mary","Campione","Snowboarding"+"[123456789]",new Integer(5),new Boolean(false)},
    {"Alison","Huml","Rowing"+":123456789]",new Integer(3),new Boolean(true)},
    {"Frank","Ni","Running"+":123456789", new Integer(12), new Boolean(false)},
    {"Kathy","Walrath","Chasing toddlers"+"<123456789>", new Integer(2), new Boolean(false)},
    {"Mark", "Andrews","Speed reading",new Integer(20),new Boolean(true)},
    {"Angela","Lih","Teaching high school",new Integer(36),new Boolean(false)} };
    // Row_Color_Style=Row_Color_Style_Default;
    // Row_Color_Style=Row_Color_Style_None;
    // Row_Color_Style=Row_Color_Style_Blue_Gray;
    Row_Color_Style=Row_Color_Style_Cyan_Gray;
    // Row_Color_Style=Row_Color_Style_Blue;
    // Row_Color_Style=Row_Color_Style_Gray;
    // Row_Color_Style=Row_Color_Style_Red_Green;
    // Row_Color_Style=Row_Color_Style_Green_Yellow;
    // Row_Color_Style=Row_Color_Style_Red_Yellow;
    Preffered_Width=Max_Header_Cell_Width;
    if (Demo_External_Table) demo=new Table_Panel("External Table Demo",columnNames,data,data.length,false,Demo_External_Table,false,Row_Color_Style,Max_Header_Cell_Width,Default_Selection_Color,true);
    else
    JFrame Table_Frame=new JFrame("Internal Table Demo");
    // demo=new Table_Panel(Nm_Lib.Dir_A_Test+"ELX.csv",false,Row_Color_Style,Preffered_Width,null);
    // demo=new Table_Panel(Nm_Lib.Dir_Stock_Data+"ABV_Data.txt",false,Row_Color_Style,Preffered_Width," ");
    demo=new Table_Panel("C:/Dir_Stock_Data/EOP.txt",",",false);
    // demo=new Table_Panel(Nm_Lib.Dir_Stock_Data+"ABV_Data.txt"," ",false);
    Table_Frame.getContentPane().add(demo.scrollPane);
    Table_Frame.addWindowListener(new WindowAdapter()
    public void windowActivated(WindowEvent e) { }
    public void windowClosed(WindowEvent e) { }
    public void windowClosing(WindowEvent e) { System.exit(0); }
    public void windowDeactivated(WindowEvent e) { }
    public void windowDeiconified(WindowEvent e) { demo.repaint(); }
    public void windowGainedFocus(WindowEvent e) { demo.repaint(); }
    public void windowIconified(WindowEvent e) { }
    public void windowLostFocus(WindowEvent e) { }
    public void windowOpening(WindowEvent e) { demo.repaint(); }
    public void windowOpened(WindowEvent e) { }
    public void windowResized(WindowEvent e) { demo.repaint(); }
    public void windowStateChanged(WindowEvent e) { demo.repaint(); }
    Table_Frame.pack();
    Table_Frame.setBounds((Screen_Size.width-Table_Frame.getWidth())/2,(Screen_Size.height-Table_Frame.getHeight())/2,Table_Frame.getWidth(),Table_Frame.getHeight());
    Table_Frame.setVisible(true);
    public static void main(String[] args)
    // Schedule a job for the event-dispatching thread : creating and showing this application's GUI.
    SwingUtilities.invokeLater(new Runnable() { public void run() { Create_And_Show_GUI(); } });
    * TableSorter is a decorator for TableModels; adding sorting functionality to a supplied TableModel. TableSorter does not store
    * or copy the data in its TableModel; instead it maintains a map from the row indexes of the view to the row indexes of the
    * model. As requests are made of the sorter (like getValueAt(row, col)) they are passed to the underlying model after the row numbers
    * have been translated via the internal mapping array. This way, the TableSorter appears to hold another copy of the table
    * with the rows in a different order.
    * <p/>
    * TableSorter registers itself as a listener to the underlying model, just as the JTable itself would. Events recieved from the model
    * are examined, sometimes manipulated (typically widened), and then passed on to the TableSorter's listeners (typically the JTable).
    * If a change to the model has invalidated the order of TableSorter's rows, a note of this is made and the sorter will resort the
    * rows the next time a value is requested.
    * <p/>
    * When the tableHeader property is set, either by using the setTableHeader() method or the two argument constructor, the table
    * header may be used as a complete UI for TableSorter. The default renderer of the tableHeader is decorated with a renderer
    * that indicates the sorting status of each column. In addition, a mouse listener is installed with the following behavior:
    * <ul>
    * <li>
    * Mouse-click: Clears the sorting status of all other columns and advances the sorting status of that column through three
    * values: {NOT_SORTED, ASCENDING, DESCENDING} (then back to NOT_SORTED again).
    * <li>
    * SHIFT-mouse-click: Clears the sorting status of all other columns and cycles the sorting status of the column through the same
    * three values, in the opposite order: {NOT_SORTED, DESCENDING, ASCENDING}.
    * <li>
    * CONTROL-mouse-click and CONTROL-SHIFT-mouse-click: as above except that the changes to the column do not cancel the statuses of columns
    * that are already sorting - giving a way to initiate a compound sort.
    * </ul>
    * <p/>
    * This is a long overdue rewrite of a class of the same name that first appeared in the swing table demos in 1997.
    * @author Philip Milne
    * @author Brendon McLean
    * @author Dan van Enckevort
    * @author Parwinder Sekhon
    * @version 2.0 02/27/04
    class TableSorter extends AbstractTableModel
    public static final long serialVersionUID=26362862L;
    protected TableModel tableModel;
    public static final int DESCENDING = -1;
    public static final int NOT_SORTED = 0;
    public static final int ASCENDING = 1;
    private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED);
    public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() { public int compare(Object o1, Object o2) { return ((Comparable) o1).compareTo(o2); } };
    public static final Comparator LEXICAL_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); } };
    private Row[] viewToModel;
    private int[] modelToView;
    private JTableHeader tableHeader;
    private MouseListener mouseListener;
    private TableModelListener tableModelListener;
    private Map<Class,Comparator> columnComparators = new HashMap<Class,Comparator>();
    private List<Directive> sortingColumns = new ArrayList<Directive>();
    public TableSorter()
    this.mouseListener = new MouseHandler();
    this.tableModelListener = new TableModelHandler();
    public TableSorter(TableModel tableModel)
    this();
    setTableModel(tableModel);
    public TableSorter(TableModel tableModel, JTableHeader tableHeader)
    this();
    setTableHeader(tableHeader);
    setTableModel(tableModel);
    private void clearSortingState()
    viewToModel = null;
    modelToView = null;
    public TableModel getTableModel() { return tableModel; }
    public void setTableModel(TableModel tableModel)
    if (this.tableModel != null) { this.tableModel.removeTableModelListener(tableModelListener); }
    this.tableModel = tableModel;
    if (this.tableModel != null) { this.tableModel.addTableModelListener(tableModelListener); }
    clearSortingState();
    fireTableStructureChanged();
    public JTableHeader getTableHeader() { return tableHeader; }
    public void setTableHeader(JTableHeader tableHeader)
    if (this.tableHeader != null)
    this.tableHeader.removeMouseListener(mouseListener);
    TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer();
    if (defaultRenderer instanceof SortableHeaderRenderer) this.tableHeader.setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer);
    this.tableHeader = tableHeader;
    if (this.tableHeader != null)
    this.tableHeader.addMouseListener(mouseListener);
    this.tableHeader.setDefaultRenderer(
    new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer()));
    public boolean isSorting() { return sortingColumns.size() != 0; }
    private Directive getDirective(int column)
    for (int i = 0; i < sortingColumns.size(); i++)
    Directive directive = (Directive)sortingColumns.get(i);
    if (directive.column == column) { return directive; }
    return EMPTY_DIRECTIVE;
    public int getSortingStatus(int column) { return getDirective(column).direction; }
    private void sortingStatusChanged()
    clearSortingState();
    fireTableDataChanged();
    if (tableHeader != null) { tableHeader.repaint(); }
    public void setSortingStatus(int column, int status)
    Directive directive = getDirective(column);
    if (directive != EMPTY_DIRECTIVE) { sortingColumns.remove(directive); }
    if (status != NOT_SORTED) { sortingColumns.add(new Directive(column, status)); }
    sortingStatusChanged();
    protected Icon getHeaderRendererIcon(int column, int size)
    Directive directive = getDirective(column);
    if (directive == EMPTY_DIRECTIVE) { return null; }
    return new Arrow(directive.direction == DESCENDING, size, sortingColumns.indexOf(directive));
    private void cancelSorting()
    sortingColumns.clear();
    sortingStatusChanged();
    public void setColumnComparator(Class type, Comparator comparator)
    if (comparator == null) { columnComparators.remove(type); }
    else { columnComparators.put(type, comparator); }
    protected Comparator getComparator(int column)
    Class columnType = tableModel.getColumnClass(column);
    Comparator comparator = (Comparator) columnComparators.get(columnType);
    if (comparator != null) { return comparator; }
    if (Comparable.class.isAssignableFrom(columnType)) { return COMPARABLE_COMAPRATOR; }
    return LEXICAL_COMPARATOR;
    private Row[] getViewToModel()
    if (viewToModel == null)
    int tableModelRowCount = tableModel.getRowCount();
    viewToModel = new Row[tableModelRowCount];
    for (int row = 0; row < tableModelRowCount; row++) { viewToModel[row] = new Row(row); }
    if (isSorting()) { Arrays.sort(viewToModel); }
    return viewToModel;
    public int modelIndex(int viewIndex) { return getViewToModel()[viewIndex].modelIndex; }
    private int[] getModelToView()
    if (modelToView == null)
    int n = getViewToModel().length;
    modelToView = new int[n];
    for (int i = 0; i < n; i++) { modelToView[modelIndex(i)] = i; }
    return modelToView;
    // TableModel interface methods
    public int getRowCount() { return (tableModel == null) ? 0 : tableModel.getRowCount(); }
    public int getColumnCount() { return (tableModel == null) ? 0 : tableModel.getColumnCount(); }
    public String getColumnName(int column) { return tableModel.getColumnName(column); }
    public Class getColumnClass(int column) { return tableModel.getColumnClass(column); }
    public boolean isCellEditable(int row, int column) { return tableModel.isCellEditable(modelIndex(row), column); }
    public Object getValueAt(int row, int column) { return tableModel.getValueAt(modelIndex(row), column); }
    public void setValueAt(Object aValue, int row, int column) { tableModel.setValueAt(aValue, modelIndex(row), column); }
    // Helper classes
    private class Row implements Comparable
    private int modelIndex;
    public Row(int index) { this.modelIndex = index; }
    public int compareTo(Object o)
    int row1 = modelIndex;
    int row2 = ((Row) o).modelIndex;
    for (Iterator it = sortingColumns.iterator(); it.hasNext();)
    Directive directive = (Directive) it.next();
    int column = directive.column;
    Object o1 = tableModel.getValueAt(row1, column);
    Object o2 = tableModel.getValueAt(row2, column);
    int comparison = 0;
    // Define null less than everything, except null.

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.table.*;
    import java.io.*;
    import java.sql.*;
    import java.util.*;
    import java.util.List;
    import javax.swing.event.TableModelEvent;
    import javax.swing.event.TableModelListener;
    public class Table_Panel extends JPanel implements ItemListener
      public static final long serialVersionUID=26362862L;
      static final int Row_Color_Style_Default=-1,Row_Color_Style_None=0,Row_Color_Style_Blue_Gray=1,Row_Color_Style_Cyan_Gray=2,Row_Color_Style_Blue=3,
                       Row_Color_Style_Gray=4,Row_Color_Style_Red_Green=5,Row_Color_Style_Green_Yellow=6,Row_Color_Style_Red_Yellow=7,
                       Max_Header_Cell_Width=0,Header_Width=1,Cell_Width=2;
      static int Row_Color_Style=Row_Color_Style_Cyan_Gray,Preffered_Width=Header_Width;
    //  static int Row_Color_Style=Row_Color_Style_None,Preffered_Width=Header_Width;
    //boolean        Debug=true,
      boolean        Debug=false,
    //               Use_Row_Colors=true,
                     Use_Row_Colors=false;
      JFrame Table_Frame;
      TableModel My_Model;
      JScrollPane scrollPane=new JScrollPane();
      public JTable Table;
      static String columnNames[],Default_Delimiter=",";
      Object[][] data;
      static Dimension Screen_Size=Toolkit.getDefaultToolkit().getScreenSize();
      int Column_Width[];
      static Color Default_Selection_Color=new Color(250,135,200);
      Color Selection_Color=Default_Selection_Color;
      public Table_Panel(ResultSet RS,String Table_Name,boolean Show_External_Table,int Row_Color_Style,int Preffered_Width,boolean In_Original_Order)
        String Value,Table_Column_Names[]=null;
        Object[][] Table_Data=null;
        int Row_Count,Index=0;
        try
          if (RS==null) return;
          else
            RS.last();
            Row_Count=RS.getRow();
            RS.beforeFirst();
          ResultSetMetaData rsmd=RS.getMetaData();
          int Column_Count=rsmd.getColumnCount();
          Table_Column_Names=new String[Column_Count];
          Table_Data=new Object[Row_Count][Column_Count];
          for (int i=1;i<=Column_Count;i++) Table_Column_Names[i-1]=rsmd.getColumnLabel(i);            // Get column names
    //Out("Row_Count="+Row_Count+"  Column_Count="+Column_Count);
          while (RS.next())                                                                            // Get all rows
            for (int i=1;i<=Column_Count;i++)
              Value=RS.getString(i);
              Table_Data[Index][i-1]=(Value==null)?"null":Value;
            Index++;
    //      if (Test_Ct++>300) break;
        catch (Exception e) { e.printStackTrace(); }
        scrollPane=new Table_Panel(Table_Name,Table_Column_Names,Table_Data,Table_Data.length,false,Show_External_Table,false,Row_Color_Style,Preffered_Width,Selection_Color,In_Original_Order).scrollPane;
      public Table_Panel(String[] Table_Column_Names,Object[][] Table_Data,Color Selection_Color,boolean In_Original_Order)
        this("",Table_Column_Names,Table_Data,Table_Data.length,false,false,false,Row_Color_Style,Preffered_Width,Selection_Color,In_Original_Order);
      public Table_Panel(String Table_Name,String[] Table_Column_Names,Object[][] Table_Data,boolean Show_External_Table,Color Selection_Color,boolean In_Original_Order)
        this(Table_Name,Table_Column_Names,Table_Data,Table_Data.length,false,Show_External_Table,false,Row_Color_Style,Preffered_Width,Selection_Color,In_Original_Order);
      public Table_Panel(String Table_Name,String[] Table_Column_Names,Object[][] Table_Data,int Row_Count,boolean Is_Child,boolean Show_External_Table,boolean Manage_Attachment,int Row_Color_Style,int Preffered_Width,Color Selection_Color,boolean In_Original_Order)
        columnNames=Table_Column_Names;
        if (In_Original_Order) data=Table_Data;
        else
          data=new Object[Table_Data.length][columnNames.length];
          for (int row=0;row<Table_Data.length;row++)
            data[row]=new Object[columnNames.length];
            for (int Column=0;Column<Table_Data[row].length;Column++) data[row][Column]=Table_Data[Table_Data.length-1-row][Column];
        Column_Width=new int[columnNames.length];
        this.Row_Color_Style=Row_Color_Style;
        Use_Row_Colors=(Row_Color_Style!=Row_Color_Style_None);
        this.Preffered_Width=Preffered_Width;
        if (Selection_Color!=null) this.Selection_Color=Selection_Color;
    //    Out("this.Selection_Color="+this.Selection_Color);
    //    TableModel My_Model=new DefaultTableModel(Table_Data,columnNames)
        TableModel My_Model=new DefaultTableModel(data,columnNames)
          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)
    //      Out(row+","+col+"["+data[row][col]+"]   data.length="+data.length+"  data[0].length="+data[0].length);
            return (data[row][col]==null)?"":((data[row][col] instanceof Boolean)?data[row][col]:data[row][col].toString()); // Non-boolean values will have bgcolor
          public Class getColumnClass(int column)
            Class returnValue;
            if ((column>=0) && (column<getColumnCount())) returnValue=getValueAt(0,column).getClass();
            else returnValue=Object.class;
            return returnValue;
        // 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<0) 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)
            String Execution_Dir=getClass().getProtectionDomain().getCodeSource().getLocation().toString();
            if (Debug) System.out.println("Execution_Dir="+Execution_Dir+"\nLast_Value="+Table_Grid_Cell_Renderer.Last_Value+"  Setting value at [ "+row+","+col+" ] to "+value+" (an instance of "+value.getClass()+")");
            if (Execution_Dir.toLowerCase().indexOf("c:/")!=-1 || value.getClass()==Boolean.class || !Use_Row_Colors) data[row][col]=value;
    //     else data[row][col]=(Table_Grid_CellRenderer.Last_Value==null)?value:value.toString().substring(Table_Grid_CellRenderer.Last_Value.toString().length());
            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("--------------------------------------------------------------------------");
        TableSorter sorter=new TableSorter(My_Model);
        Table=new JTable(sorter)
    //    Table=new JTable(My_Model)
          public static final long serialVersionUID=26362862L;
          public String getToolTipText(MouseEvent e)           // Implement table cell tool tips.
            Object Cell_Tip;
            String tip=null;
            java.awt.Point p=e.getPoint();
            int rowIndex=rowAtPoint(p);
            int colIndex=columnAtPoint(p);
            int realColumnIndex=convertColumnIndexToModel(colIndex);
            Cell_Tip=getValueAt(rowIndex,colIndex);
    //        if (realColumnIndex == 2)                         //Sport column
              tip=Cell_Tip.toString();
            else if (realColumnIndex == 4)                      //Veggie column
              TableModel model=getModel();
              String firstName=(String)model.getValueAt(rowIndex,0);
              String lastName=(String)model.getValueAt(rowIndex,1);
              Boolean veggie=(Boolean)model.getValueAt(rowIndex,4);
              if (Boolean.TRUE.equals(veggie)) tip=firstName+" "+lastName+" is a vegetarian";
              else tip=firstName+" "+lastName+" is not a vegetarian";
            else
              // You can omit this part if you know you don't have any renderers that supply their own tool tips.
              tip=super.getToolTipText(e);
            return tip;
    //    RowSorter<TableModel> sorter=new TableRowSorter<TableModel>(My_Model);
    //    Table.setRowSorter(sorter);
        Table.setSelectionBackground(this.Selection_Color);
        int Table_Height=Table.getRowHeight()*Row_Count;
        // sorter.addMouseListenerToHeaderInTable(Table);      // ADDED THIS
        sorter.setTableHeader(Table.getTableHeader());
        if (Table_Column_Names.length>20) Table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        if (Manage_Attachment) Table.setPreferredScrollableViewportSize(new Dimension(500,(Table_Height>850)?850:Table_Height));
        else Table.setPreferredScrollableViewportSize(new Dimension(1000,(Table_Height>850)?850:Table_Height));
        if (Use_Row_Colors) Table.setDefaultRenderer(Object.class,new Table_Grid_Cell_Renderer());
        //Create the scroll pane and add the table to it.
        scrollPane=new JScrollPane(Table);
        //Set up column sizes.
        initColumnSizes(Table,My_Model);
        //Add the scroll pane to this window.
        if (Show_External_Table)
          Table_Frame=new JFrame(Table_Name);
          Table_Frame.getContentPane().add(scrollPane);
          Table_Frame.addWindowListener(new WindowAdapter()
            public void windowActivated(WindowEvent e) { }
            public void windowClosed(WindowEvent e) { }
            public void windowClosing(WindowEvent e)  { System.exit(0); }
            public void windowDeactivated(WindowEvent e)  { }
            public void windowDeiconified(WindowEvent e)  { scrollPane.repaint(); }
            public void windowGainedFocus(WindowEvent e)  { scrollPane.repaint(); }
            public void windowIconified(WindowEvent e)  { }
            public void windowLostFocus(WindowEvent e)  { }
            public void windowOpening(WindowEvent e) { scrollPane.repaint(); }
            public void windowOpened(WindowEvent e)  { }
            public void windowResized(WindowEvent e) { scrollPane.repaint(); } 
            public void windowStateChanged(WindowEvent e) { scrollPane.repaint(); }
          Table_Frame.pack();
          Table_Frame.setBounds((Screen_Size.width-Table_Frame.getWidth())/2,(Screen_Size.height-Table_Frame.getHeight())/2,Table_Frame.getWidth(),Table_Frame.getHeight());
          Table_Frame.setVisible(true);
          if (Is_Child) Table_Frame.addComponentListener(new ComponentAdapter() { public void componentClosing(ComponentEvent e) { System.exit(0); } });
        else add(scrollPane);
      public Table_Panel(String File_Name) { this(File_Name,false,Row_Color_Style_Cyan_Gray,Preffered_Width,null,Default_Selection_Color,true); }
      public Table_Panel(String File_Name,int Row_Color_Style,boolean In_Original_Order) { this(File_Name,false,Row_Color_Style,Preffered_Width,null,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,String Delimiter,boolean In_Original_Order) { this(File_Name,false,Row_Color_Style_Cyan_Gray,Preffered_Width,Delimiter,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,int Preffered_Width,String Delimiter,boolean In_Original_Order) { this(File_Name,false,Row_Color_Style,Preffered_Width,Delimiter,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,int Row_Color_Style,int Preffered_Width,String Delimiter,boolean In_Original_Order) { this(File_Name,false,Row_Color_Style,Preffered_Width,Delimiter,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,boolean Show_External_Table,boolean In_Original_Order) { this(File_Name,Show_External_Table,Row_Color_Style,Preffered_Width,null,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,boolean Show_External_Table,String Delimiter,boolean In_Original_Order) { this(File_Name,Show_External_Table,Row_Color_Style,Preffered_Width,Delimiter,Default_Selection_Color,In_Original_Order); }
      public Table_Panel(String File_Name,boolean Show_External_Table,int Row_Color_Style,int Preffered_Width,String Delimiter,Color Selection_Color,boolean In_Original_Order)
        String Table_Column_Names[],Column_Name_Line="";
        int Row_Count=0,Index=0;
        boolean Is_Child=false,Manage_Attachment=false;
        StringTokenizer ST;
        if (Delimiter==null) Delimiter=Default_Delimiter;
        if (new File(File_Name).exists())
          try
            String Line,Str=Tool_Lib.Read_File(File_Name).toString();
            ST=new StringTokenizer(Str,"\n");
            Line=ST.nextToken();
            Row_Count=ST.countTokens();
            Object[][] Table_Data=new Object[Row_Count][];
            if (Delimiter.equals(" ")) Line=Line.replaceAll(" {2,}"," ").trim();     // Replace multiple spaces with the delimiter space
            Table_Column_Names=Line.split(Delimiter);
            columnNames=Table_Column_Names;
            for (int i=0;i<Table_Column_Names.length;i++) Column_Name_Line+=Table_Column_Names[i]+"  ";
    //Out("Column_Name_Line [ "+Table_Column_Names.length+" ]="+Column_Name_Line);
            while (ST.hasMoreTokens())
              Line=ST.nextToken();
    //Out(Line);
              if (Delimiter.equals(" ")) Line=Line.replaceAll(" {2,}"," ").trim();   // Replace multiple spaces with the delimiter space
              if (Line.indexOf(Delimiter)!=-1) Table_Data[Index]=Line.split(Delimiter);
              else
                Table_Data[Index]=new Object[Table_Column_Names.length];
                Table_Data[Index][0]=Line;
                for (int i=1;i<Table_Column_Names.length;i++) Table_Data[Index]="";
    Index++;
    Line="";
    for (int i=0;i<Table_Data.length;i++)
    Line+="[ "+Table_Data[i].length+" ] ";
    for (int j=0;j<Table_Data[i].length;j++) Line+=Table_Data[i][j]+" ";
    Line+="\n";
    Out(Line);
    Table_Panel A_Table_Panel=new Table_Panel(File_Name,Table_Column_Names,Table_Data,Row_Count,Is_Child,Show_External_Table,Manage_Attachment,Row_Color_Style,Preffered_Width,Selection_Color,In_Original_Order);
    Table=A_Table_Panel.Table;
    scrollPane=A_Table_Panel.scrollPane;
    Column_Width=A_Table_Panel.Column_Width;
    data=A_Table_Panel.data;
    catch (Exception e) { e.printStackTrace(); }
    public void setPreferredSize(Dimension A_Dimension) { scrollPane.setPreferredSize(A_Dimension); }
    // 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().
    void initColumnSizes(JTable table,TableModel model)
    TableColumn column=null;
    Component comp=null;
    int headerWidth=0,cellWidth=0;
    Object[] longValues=(data.length>0)?data[0]:null;
    TableCellRenderer headerRenderer=table.getTableHeader().getDefaultRenderer();
    if (data.length<1) return;
    for (int i=0;i<model.getColumnCount();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;
    switch (Preffered_Width)
    case Max_Header_Cell_Width : column.setPreferredWidth(Math.max(headerWidth,cellWidth));break;
    case Header_Width : column.setPreferredWidth(headerWidth);break;
    case Cell_Width : column.setPreferredWidth(cellWidth);break;
    Column_Width[i]=column.getPreferredWidth();
    if (Debug) Out("Initializing width of column "+i+". "+"headerWidth="+headerWidth+"; cellWidth="+cellWidth+" Column_Width["+i+"]="+Column_Width[i]);
    // Detects a state change in any of the Lists. Resets the variable corresponding to the selected item in a particular List. Invokes changeFont with the currently selected fontname, style and size attributes.
    public void itemStateChanged(ItemEvent e)
    Out(e.toString());
    if (e.getStateChange() != ItemEvent.SELECTED) return;
    Object list=e.getSource();
    public static void Out(String message) { System.out.println(message); }
    // Create the GUI and show it. For thread safety, this method should be invoked from the event-dispatching thread.
    static void Create_And_Show_GUI()
    boolean Demo_External_Table=true;
    // boolean Demo_External_Table=false;
    final Table_Panel demo;
    String[] columnNames={"First Names","Last Names","Sport","Num of Years","Vegetarian"};
    Object[][] data={{"Mary","Campione","Snowboarding"+"[123456789]",new Integer(5),new Boolean(false)},
    {"Alison","Huml","Rowing"+":123456789]",new Integer(3),new Boolean(true)},
    {"Frank","Ni","Running"+":123456789", new Integer(12), new Boolean(false)},
    {"Kathy","Walrath","Chasing toddlers"+"<123456789>", new Integer(2), new Boolean(false)},
    {"Mark", "Andrews","Speed reading",new Integer(20),new Boolean(true)},
    {"Angela","Lih","Teaching high school",new Integer(36),new Boolean(false)} };
    // Row_Color_Style=Row_Color_Style_Default;
    // Row_Color_Style=Row_Color_Style_None;
    // Row_Color_Style=Row_Color_Style_Blue_Gray;
    Row_Color_Style=Row_Color_Style_Cyan_Gray;
    // Row_Color_Style=Row_Color_Style_Blue;
    // Row_Color_Style=Row_Color_Style_Gray;
    // Row_Color_Style=Row_Color_Style_Red_Green;
    // Row_Color_Style=Row_Color_Style_Green_Yellow;
    // Row_Color_Style=Row_Color_Style_Red_Yellow;
    Preffered_Width=Max_Header_Cell_Width;
    if (Demo_External_Table) demo=new Table_Panel("External Table Demo",columnNames,data,data.length,false,Demo_External_Table,false,Row_Color_Style,Max_Header_Cell_Width,Default_Selection_Color,true);
    else
    JFrame Table_Frame=new JFrame("Internal Table Demo");
    // demo=new Table_Panel(Nm_Lib.Dir_A_Test+"ELX.csv",false,Row_Color_Style,Preffered_Width,null);
    // demo=new Table_Panel(Nm_Lib.Dir_Stock_Data+"ABV_Data.txt",false,Row_Color_Style,Preffered_Width," ");
    demo=new Table_Panel("C:/Dir_Stock_Data/EOP.txt",",",false);
    // demo=new Table_Panel(Nm_Lib.Dir_Stock_Data+"ABV_Data.txt"," ",false);
    Table_Frame.getContentPane().add(demo.scrollPane);
    Table_Frame.addWindowListener(new WindowAdapter()
    public void windowActivated(WindowEvent e) { }
    public void windowClosed(WindowEvent e) { }
    public void windowClosing(WindowEvent e) { System.exit(0); }
    public void windowDeactivated(WindowEvent e) { }
    public void windowDeiconified(WindowEvent e) { demo.repaint(); }
    public void windowGainedFocus(WindowEvent e) { demo.repaint(); }
    public void windowIconified(WindowEvent e) { }
    public void windowLostFocus(WindowEvent e) { }
    public void windowOpening(WindowEvent e) { demo.repaint(); }
    public void windowOpened(WindowEvent e) { }
    public void windowResized(WindowEvent e) { demo.repaint(); }
    public void windowStateChanged(WindowEvent e) { demo.repaint(); }
    Table_Frame.pack();
    Table_Frame.setBounds((Screen_Size.width-Table_Frame.getWidth())/2,(Screen_Size.height-Table_Frame.getHeight())/2,Table_Frame.getWidth(),Table_Frame.getHeight());
    Table_Frame.setVisible(true);
    public static void main(String[] args)
    // Schedule a job for the event-dispatching thread : creating and showing this application's GUI.
    SwingUtilities.invokeLater(new Runnable() { public void run() { Create_And_Show_GUI(); } });
    * TableSorter is a decorator for TableModels; adding sorting functionality to a supplied TableModel. TableSorter does not store
    * or copy the data in its TableModel; instead it maintains a map from the row indexes of the view to the row indexes of the
    * model. As requests are made of the sorter (like getValueAt(row, col)) they are passed to the underlying model after the row numbers
    * have been translated via the internal mapping array. This way, the TableSorter appears to hold another copy of the table
    * with the rows in a different order.
    * <p/>
    * TableSorter registers itself as a listener to the underlying model, just as the JTable itself would. Events recieved from the model
    * are examined, sometimes manipulated (typically widened), and then passed on to the TableSorter's listeners (typically the JTable).
    * If a change to the model has invalidated the order of TableSorter's rows, a note of this is made and the sorter will resort the
    * rows the next time a value is requested.
    * <p/>
    * When the tableHeader property is set, either by using the setTableHeader() method or the two argument constructor, the table
    * header may be used as a complete UI for TableSorter. The default renderer of the tableHeader is decorated with a renderer
    * that indicates the sorting status of each column. In addition, a mouse listener is installed with the following behavior:
    * <ul>
    * <li>
    * Mouse-click: Clears the sorting status of all other columns and advances the sorting status of that column through three
    * values: {NOT_SORTED, ASCENDING, DESCENDING} (then back to NOT_SORTED again).
    * <li>
    * SHIFT-mouse-click: Clears the sorting status of all other columns and cycles the sorting status of the column through the same
    * three values, in the opposite order: {NOT_SORTED, DESCENDING, ASCENDING}.
    * <li>
    * CONTROL-mouse-click and CONTROL-SHIFT-mouse-click: as above except that the changes to the column do not cancel the statuses of columns
    * that are already sorting - giving a way to initiate a compound sort.
    * </ul>
    * <p/>
    * This is a long overdue rewrite of a class of the same name that first appeared in the swing table demos in 1997.
    * @author Philip Milne
    * @author Brendon McLean
    * @author Dan van Enckevort
    * @author Parwinder Sekhon
    * @version 2.0 02/27/04
    class TableSorter extends AbstractTableModel
    public static final long serialVersionUID=26362862L;
    protected TableModel tableModel;
    public static final int DESCENDING = -1;
    public static final int NOT_SORTED = 0;
    public static final int ASCENDING = 1;
    private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED);
    public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() { public int compare(Object o1, Object o2) { return ((Comparable) o1).compareTo(o2); } };
    public static final Comparator LEXICAL_COMPARATOR = new Comparator() { public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); } };
    private Row[] viewToModel;
    private int[] modelToView;
    private JTableHeader tableHeader;
    private MouseListener mouseListener;
    private TableModelListener tableModelListener;
    private Map<Class,Comparator> columnComparators = new HashMap<Class,Comparator>();
    private List<Directive> sortingColumns = new ArrayList<Directive>();
    public TableSorter()
    this.mouseListener = new MouseHandler();
    this.tableModelListener = new TableModelHandler();
    public TableSorter(TableModel tableModel)
    this();
    setTableModel(tableModel);
    public TableSorter(TableModel tableModel, JTableHeader tableHeader)
    this();
    setTableHeader(tableHeader);
    setTableModel(tableModel);
    private void clearSortingState()
    viewToModel = null;
    modelToView = null;
    public TableModel getTableModel() { return tableModel; }
    public void setTableModel(TableModel tableModel)
    if (this.tableModel != null) { this.tableModel.removeTableModelListener(tableModelListener); }
    this.tableModel = tableModel;
    if (this.tableModel != null) { this.tableModel.addTableModelListener(tableModelListener); }
    clearSortingState();
    fireTableStructureChanged();
    public JTableHeader getTableHeader() { return tableHeader; }
    public void setTableHeader(JTableHeader tableHeader)
    if (this.tableHeader != null)
    this.tableHeader.removeMouseListener(mouseListener);
    TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer();
    if (defaultRenderer instanceof SortableHeaderRenderer) this.tableHeader.setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer);
    this.tableHeader = tableHeader;
    if (this.tableHeader != null)
    this.tableHeader.addMouseListener(mouseListener);
    this.tableHeader.setDefaultRenderer(
    new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer()));
    public boolean isSorting() { return sortingColumns.size() != 0; }
    private Directive getDirective(int column)
    for (int i = 0; i < sortingColumns.size(); i++)
    Directive directive = (Directive)sortingColumns.get(i);
    if (directive.column == column) { return directive; }
    return EMPTY_DIRECTIVE;
    public int getSortingStatus(int column) { return getDirective(column).direction; }
    private void sortingStatusChanged()
    clearSortingState();
    fireTableDataChanged();
    if (tableHeader != null) { tableHeader.repaint(); }
    public void setSortingStatus(int column, int status)
    Directive directive = getDirective(column);
    if (directive != EMPTY_DIRECTIVE) { sortingColumns.remove(directive); }
    if (status != NOT_SORTED) { sortingColumns.add(new Directive(column, status)); }
    sortingStatusChanged();
    protected Icon getHeaderRendererIcon(int column, int size)
    Directive directive = getDirective(column);
    if (directive == EMPTY_DIRECTIVE) { return null; }
    return new Arrow(directive.direction == DESCENDING, size, sortingColumns.indexOf(directive));
    private void cancelSorting()
    sortingColumns.clear();
    sortingStatusChanged();
    public void setColumnComparator(Class type, Comparator comparator)
    if (comparator == null) { columnComparators.remove(type); }
    else { columnComparators.put(type, comparator); }
    protected Comparator getComparator(int column)
    Class columnType = tableModel.getColumnClass(column);
    Comparator comparator = (Comparator) columnComparators.get(columnType);
    if (comparator != null) { return comparator; }
    if (Comparable.class.isAssignableFrom(columnType)) { return COMPARABLE_COMAPRATOR; }
    return LEXICAL_COMPARATOR;
    private Row[] getViewToModel()
    if (viewToModel == null)
    int tableModelRowCount = tableModel.getRowCount();
    viewToModel = new Row[tableModelRowCount];
    for (int row = 0; row < tableModelRowCount; row++) { viewToModel[row] = new Row(row); }
    if (isSorting()) { Arrays.sort(viewToModel); }
    return viewToModel;
    public int modelIndex(int viewIndex) { return getViewToModel()[viewIndex].modelIndex; }
    private int[] getModelToView()
    if (modelToView == null)
    int n = getViewToModel().length;
    modelToView = new int[n];
    for (int i = 0; i < n; i++) { modelToView[modelIndex(i)] = i; }
    return modelToView;
    // TableModel interface methods
    public int getRowCount() { return (tableModel == null) ? 0 : tableModel.getRowCount(); }
    public int getColumnCount() { return (tableModel == null) ? 0 : tableModel.getColumnCount(); }
    public String getColumnName(int column) { return tableModel.getColumnName(column); }
    public Class getColumnClass(int column) { return tableModel.getColumnClass(column); }
    public boolean isCellEditable(int row, int column) { return tableModel.isCellEditable(modelIndex(row), column); }
    public Object getValueAt(int row, int column) { return tableModel.getValueAt(modelIndex(row), column); }
    public void setValueAt(Object aValue, int row, int column) { tableModel.setValueAt(aValue, modelIndex(row), column); }
    // Helper classes
    private class Row implements Comparable
    private int modelIndex;
    public Row(int index) { this.modelIndex = index; }
    public int compareTo(Object o)
    int row1 = modelIndex;
    int row2 = ((Row) o).modelIndex;
    for (Iterator it = sortingColumns.iterator(); it.hasNext();)
    Directive directive = (Directive) it.next();
    int column = directive.column;
    Object o1 = tableModel.getValueAt(row1, column);
    Object o2 = tableModel.getValueAt(row2, column);
    int comparison = 0;
    // Define null less than everything, except null.
    if (o1 == null && o2 == null) { comparison = 0; }
    else if (o1 == null) { comparison = -1; }
    else if (o2 == null) { comparison = 1; }
    else { comparison = getComparator(column).compare(o1, o2); }
    if (comparison != 0) { return directive.direction == DESCENDING ? -comparison : comparison; }
    return 0;
    private class TableModelHandler implements TableModelListener
    public void tableChanged(TableModelEvent e)
    // If we're not sorting by anything

  • Editing a JTable Feild (setValueAt)

    Hi, I have a series of tables that each pull different data from a database and then desplay the data to the user. The user has the ability to update the shown data by editing the field(s) displayed in the table. To complete the update, I want to error check their change (to make sure they didn't leave the field blank for example) and then I want to update the database before allowing the new value to be the one that's shown in the table. In other words if error checking or updating the database result in an error, an error message is displayed and the origional value is left in the "updated" field.
    What I was doing to accomplish this was adding a custom Table Model to each table with error checking code in the setValueAt method of the Table Model.
    Now, I want a standard table model that all of my tables use to reduce the number of classes I have from 1 frame, x number of table models to 1 frame, 1 table model. The problem I'm having is, by standardizing the table model, I have to remove all error checking and database updates as they are unique to each individual table. I've tryed to add TableModelListeners to my frame but I found out that the TableModelListener is executed after the setValueAt in the Table Model. This won't work for me as, while I can error check and update the newly changed data, if there is an error, I can't revert back to what was previously displayed without recalling the database.
    I guess what my questions are are: What can I do to stop setValueAt from running until after I've error checked. Also, what tells the table/table model about the end of an edit and calls setValueAt in the first place?
    Any help would be wonderful. Thanks in advance!
    --Ethan                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

    what I think you should do is this: extend this class (which i found on the sun site) and extend it for your needs.
    the idea is to have a model as a proxy of the real model - this model holds a different model inside it and before activiating it it can do stuff, meaning - before call the "real" setValueAt you can do error checking.
    I'm also adding the SortModel which I found to be very helpful - it allows you to sort any table with 0 code. (and it's a nice example to how to use the TableMap class.
    all the luck to you.
    btw, you will still have as many tableModels, just smaller in code.
    public class TableMap extends AbstractTableModel
    implements TableModelListener {
    protected TableModel model;
    public TableModel getModel() {
    return model;
    public void setModel(TableModel model) {
    this.model = model;
    model.addTableModelListener(this);
    // By default, implement TableModel by forwarding all messages
    // to the model.
    public Object getValueAt(int aRow, int aColumn) {
    return model.getValueAt(aRow, aColumn);
    public void setValueAt(Object aValue, int aRow, int aColumn) {
    model.setValueAt(aValue, aRow, aColumn);
    public int getRowCount() {
    return (model == null) ? 0 : model.getRowCount();
    public int getColumnCount() {
    return (model == null) ? 0 : model.getColumnCount();
    public String getColumnName(int aColumn) {
    return model.getColumnName(aColumn);
    public Class getColumnClass(int aColumn) {
    return model.getColumnClass(aColumn);
    public boolean isCellEditable(int row, int column) {
    return model.isCellEditable(row, column);
    // Implementation of the TableModelListener interface,
    // By default forward all events to all the listeners.
    public void tableChanged(TableModelEvent e) {
    fireTableChanged(e);
    * A sorter for TableModels. The sorter has a model (conforming to TableModel)
    * and itself implements TableModel. TableSorter does not store or copy
    * the data in the TableModel, instead it maintains an array of
    * integers which it keeps the same size as the number of rows in its
    * model. When the model changes it notifies the sorter that something
    * has changed eg. "rowsAdded" so that its internal array of integers
    * can be reallocated. As requests are made of the sorter (like
    * getValueAt(row, col) it redirects them to its model via the mapping
    * array. That way the TableSorter appears to hold another copy of the table
    * with the rows in a different order. The sorting algorthm used is stable
    * which means that it does not move around rows when its comparison
    * function returns 0 to denote that they are equivalent.
    * @version 1.5 12/17/97
    * @author Philip Milne
    import java.util.*;
    import javax.swing.table.TableModel;
    import javax.swing.event.TableModelEvent;
    // Imports for picking up mouse events from the JTable.
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.InputEvent;
    import javax.swing.JTable;
    import javax.swing.table.JTableHeader;
    import javax.swing.table.TableColumnModel;
    public class TableSorter extends TableMap {
    int indexes[];
    Vector sortingColumns = new Vector();
    boolean ascending = true;
    int compares;
    public TableSorter() {
    indexes = new int[0]; // for consistency
    public TableSorter(TableModel model) {
    setModel(model);
    public void setModel(TableModel model) {
    super.setModel(model);
    reallocateIndexes();
    public int compareRowsByColumn(int row1, int row2, int column) {
    Class type = model.getColumnClass(column);
    TableModel data = model;
    // Check for nulls.
    Object o1 = data.getValueAt(row1, column);
    Object o2 = data.getValueAt(row2, column);
    // If both values are null, return 0.
    if (o1 == null && o2 == null) {
    return 0;
    } else if (o1 == null) { // Define null less than everything.
    return -1;
    } else if (o2 == null) {
    return 1;
    * We copy all returned values from the getValue call in case
    * an optimised model is reusing one object to return many
    * values. The Number subclasses in the JDK are immutable and
    * so will not be used in this way but other subclasses of
    * Number might want to do this to save space and avoid
    * unnecessary heap allocation.
    if (type.getSuperclass() == java.lang.Number.class) {
    Number n1 = (Number)data.getValueAt(row1, column);
    double d1 = n1.doubleValue();
    Number n2 = (Number)data.getValueAt(row2, column);
    double d2 = n2.doubleValue();
    if (d1 < d2) {
    return -1;
    } else if (d1 > d2) {
    return 1;
    } else {
    return 0;
    } else if (type == java.util.Date.class) {
    Date d1 = (Date)data.getValueAt(row1, column);
    long n1 = d1.getTime();
    Date d2 = (Date)data.getValueAt(row2, column);
    long n2 = d2.getTime();
    if (n1 < n2) {
    return -1;
    } else if (n1 > n2) {
    return 1;
    } else {
    return 0;
    } else if (type == String.class) {
    String s1 = (String)data.getValueAt(row1, column);
    String s2 = (String)data.getValueAt(row2, column);
    int result = s1.compareTo(s2);
    if (result < 0) {
    return -1;
    } else if (result > 0) {
    return 1;
    } else {
    return 0;
    } else if (type == Boolean.class) {
    Boolean bool1 = (Boolean)data.getValueAt(row1, column);
    boolean b1 = bool1.booleanValue();
    Boolean bool2 = (Boolean)data.getValueAt(row2, column);
    boolean b2 = bool2.booleanValue();
    if (b1 == b2) {
    return 0;
    } else if (b1) { // Define false < true
    return 1;
    } else {
    return -1;
    } else {
    Object v1 = data.getValueAt(row1, column);
    String s1 = v1.toString();
    Object v2 = data.getValueAt(row2, column);
    String s2 = v2.toString();
    int result = s1.compareTo(s2);
    if (result < 0) {
    return -1;
    } else if (result > 0) {
    return 1;
    } else {
         return 0;
    public int compare(int row1, int row2) {
    compares++;
    for (int level = 0; level < sortingColumns.size(); level++) {
    Integer column = (Integer)sortingColumns.elementAt(level);
    int result = compareRowsByColumn(row1, row2, column.intValue());
    if (result != 0) {
    return ascending ? result : -result;
    return 0;
    public void reallocateIndexes() {
    int rowCount = model.getRowCount();
    // Set up a new array of indexes with the right number of elements
    // for the new data model.
    indexes = new int[rowCount];
    // Initialise with the identity mapping.
    for (int row = 0; row < rowCount; row++) {
    indexes[row] = row;
    public void tableChanged(TableModelEvent e) {
    reallocateIndexes();
    super.tableChanged(e);
    public void checkModel() {
    if (indexes.length != model.getRowCount()) {
    System.err.println("Sorter not informed of a change in model.");
    public void sort(Object sender) {
    checkModel();
    compares = 0;
    // n2sort();
    // qsort(0, indexes.length-1);
    shuttlesort((int[])indexes.clone(), indexes, 0, indexes.length);
    public void n2sort() {
    for (int i = 0; i < getRowCount(); i++) {
    for (int j = i+1; j < getRowCount(); j++) {
    if (compare(indexes, indexes[j]) == -1) {
    swap(i, j);
    // This is a home-grown implementation which we have not had time
    // to research - it may perform poorly in some circumstances. It
    // requires twice the space of an in-place algorithm and makes
    // NlogN assigments shuttling the values between the two
    // arrays. The number of compares appears to vary between N-1 and
    // NlogN depending on the initial order but the main reason for
    // using it here is that, unlike qsort, it is stable.
    public void shuttlesort(int from[], int to[], int low, int high) {
    if (high - low < 2) {
    return;
    int middle = (low + high)/2;
    shuttlesort(to, from, low, middle);
    shuttlesort(to, from, middle, high);
    int p = low;
    int q = middle;
    /* This is an optional short-cut; at each recursive call,
    check to see if the elements in this subset are already
    ordered. If so, no further comparisons are needed; the
    sub-array can just be copied. The array must be copied rather
    than assigned otherwise sister calls in the recursion might
    get out of sinc. When the number of elements is three they
    are partitioned so that the first set, [low, mid), has one
            element and and the second, [mid, high), has two. We skip the
            optimisation when the number of elements is three or less as
            the first compare in the normal merge will produce the same
            sequence of steps. This optimisation seems to be worthwhile
            for partially ordered lists but some analysis is needed to
            find out how the performance drops to Nlog(N) as the initial
            order diminishes - it may drop very quickly.  */
            if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0) {
    for (int i = low; i < high; i++) {
    to[i] = from[i];
    return;
    // A normal merge.
    for (int i = low; i < high; i++) {
    if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
    to[i] = from[p++];
    else {
    to[i] = from[q++];
    public void swap(int i, int j) {
    int tmp = indexes[i];
    indexes[i] = indexes[j];
    indexes[j] = tmp;
    // The mapping only affects the contents of the data rows.
    // Pass all requests to these rows through the mapping array: "indexes".
    public Object getValueAt(int aRow, int aColumn) {
    checkModel();
    return model.getValueAt(indexes[aRow], aColumn);
    public void setValueAt(Object aValue, int aRow, int aColumn) {
    checkModel();
    model.setValueAt(aValue, indexes[aRow], aColumn);
    public void sortByColumn(int column) {
    sortByColumn(column, true);
    public void sortByColumn(int column, boolean ascending) {
    this.ascending = ascending;
    sortingColumns.removeAllElements();
    sortingColumns.addElement(new Integer(column));
    sort(this);
    super.tableChanged(new TableModelEvent(this));
    // There is no-where else to put this.
    // Add a mouse listener to the Table to trigger a table sort
    // when a column heading is clicked in the JTable.
    public void addMouseListenerToHeaderInTable(JTable table) {
    final TableSorter sorter = this;
    final JTable tableView = table;
    tableView.setColumnSelectionAllowed(false);
    MouseAdapter listMouseListener = new MouseAdapter() {
    public void mouseClicked(MouseEvent e) {
    TableColumnModel columnModel = tableView.getColumnModel();
    int viewColumn = columnModel.getColumnIndexAtX(e.getX());
    int column = tableView.convertColumnIndexToModel(viewColumn);
    if (e.getClickCount() == 1 && column != -1) {
    int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK;
    boolean ascending = (shiftPressed == 0);
    sorter.sortByColumn(column, ascending);
    JTableHeader th = tableView.getTableHeader();
    th.addMouseListener(listMouseListener);
    Glazberg.

  • JTable sorting - problem when adding elements (complete code inside)

    I�m writing this email with reference to a recent posting here but this time with the code example. (I apologize for the duplicated posting � this time it will be with the code)
    Problem: when adding more elements to the JTable (sorted) the exception: ArrayIndexOutOfBoundsException is thrown.
    Example: If the elements in the table are 10 and then the user requests for 8 � the table will produce the correct result. However, if the user will ask for 11 items (>10) the exception will be thrown.
    The program: The program below (compiles and running). A JTable is constructed with 3 items, when you click the button - the return result should be 4 items - this will generate the error, WHY?
    I would highly appreciate your thoughts why this is happening and most importantly � how to fix it.
    Thanks a lot
    3 files:
    (1) TableSorterDemo
    (2) Traveler
    (3)TableSorter
    //TableSorterDemo:
    package sorter;
    import javax.swing.DefaultListModel;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.table.AbstractTableModel;
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    * TableSorterDemo is like TableDemo, except that it
    * inserts a custom model -- a sorter -- between the table
    * and its data model.  It also has column tool tips.
    public class TableSorterDemo implements ActionListener
         private JPanel superPanel;
         private JButton clickMe = new JButton("click me to get diff data");
         private boolean DEBUG = false;
         private DefaultListModel defaultListModel;
         private JTable table;
        public TableSorterDemo()
             superPanel = new JPanel(new BorderLayout());
             defaultListModel = new DefaultListModel();
             init1();
            TableSorter sorter = new TableSorter(new MyTableModel(defaultListModel)); //ADDED THIS     
            table = new JTable(sorter);             //NEW
            sorter.setTableHeader(table.getTableHeader()); //ADDED THIS
            table.setPreferredScrollableViewportSize(new Dimension(500, 70));
            //Set up tool tips for column headers.
            table.getTableHeader().setToolTipText(
                    "Click to specify sorting; Control-Click to specify secondary sorting");
            //Create the scroll pane and add the table to it.
            JScrollPane scrollPane = new JScrollPane(table);
            //Add the scroll pane to this panel.
            superPanel.add("Center", scrollPane);
            superPanel.add("South",clickMe);
            clickMe.addActionListener(this);              
        public JPanel getPanel()
             return superPanel;
        public void init1()
             //in real life this will be done from the db
             Traveler a = new Traveler();
             Traveler b = new Traveler();
             Traveler c = new Traveler();
             a.setFirstName("Elvis");
             a.setLastName("Presley");
             a.setSprot("Ping Pong");
             a.setNumYears(3);
             a.setVegetarian(true);
             b.setFirstName("Elton");
             b.setLastName("John");
             b.setSprot("Soccer");
             b.setNumYears(2);
             b.setVegetarian(true);
             c.setFirstName("shaquille");
             c.setLastName("oneil");
             c.setSprot("Golf");
             c.setNumYears(22);
             c.setVegetarian(true);
             defaultListModel.addElement(a);
             defaultListModel.addElement(b);
             defaultListModel.addElement(c);
        public void init2()
             //in real life this will be done from the db
             Traveler d = new Traveler();
             Traveler e = new Traveler();
             Traveler f = new Traveler();
             Traveler g = new Traveler();
             d.setFirstName("John");
             d.setLastName("Smith");
             d.setSprot("Tennis");
             d.setNumYears(32);
             d.setVegetarian(true);
             e.setFirstName("Ron");
             e.setLastName("Cohen");
             e.setSprot("Baseball");
             e.setNumYears(12);
             e.setVegetarian(true);
             f.setFirstName("Donald");
             f.setLastName("Mac Novice");
             f.setSprot("Vallyball");
             f.setNumYears(1);
             f.setVegetarian(true);
             g.setFirstName("Eithan");
             g.setLastName("Superstar");
             g.setSprot("Vallyball");
             g.setNumYears(21);
             g.setVegetarian(true);
             defaultListModel.addElement(d);
             defaultListModel.addElement(e);
             defaultListModel.addElement(f);
             defaultListModel.addElement(g);            
        class MyTableModel extends AbstractTableModel
             private DefaultListModel myModel;
             public MyTableModel(DefaultListModel m)
                  myModel=m;
            private String[] columnNames = {"First Name",
                                            "Last Name",
                                            "Sport",
                                            "# of Years",
                                            "Vegetarian"};
            public int getColumnCount()
                return columnNames.length;
            public int getRowCount()
                return myModel.size();
            public String getColumnName(int column)
                 return getNames()[column];             
             public String[] getNames()
                  String[] names = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};
                  return names;
            public Object getValueAt(int row, int col)
                 return distributeObjectsInTable(row, col, (Traveler) myModel.elementAt(row));
            public Object distributeObjectsInTable(int row, int col, Traveler tr)
               switch(col)
                         case 0:
                              return tr.getFirstName();
                         case 1:
                           return tr.getLastName();
                      case 2:
                           return tr.getSprot();
                      case 3:
                           return new Integer(tr.getNumYears());
                      case 4:
                           return new Boolean (tr.isVegetarian());
                     default:
                         return "Error";
            public Class getColumnClass(int c)
                return getValueAt(0, c).getClass();
        private static void createAndShowGUI()
            //Make sure we have nice window decorations.
            JFrame.setDefaultLookAndFeelDecorated(true);
            //Create and set up the window.
            JFrame frame = new JFrame("TableSorterDemo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //Create and set up the content pane.
            TableSorterDemo newContentPane = new TableSorterDemo();
            newContentPane.getPanel().setOpaque(true); //content panes must be opaque
            frame.setContentPane(newContentPane.getPanel());
            //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();
         public void actionPerformed(ActionEvent ae)
              if (ae.getSource()==clickMe)
                   defaultListModel.removeAllElements();
                   init2(); //if the size of the model was less than 2 items - the result will be ok.
                              //in other words, if you commens the last 2 rows of this method (addElement(f) & g)
                             // the result will be fine.
                   table.updateUI();          
    }//(2) Traveler
    package sorter;
    public class Traveler
         private String firstName;
         private String lastName;
         private String sprot;
         private int numYears;
         private boolean vegetarian;
         public String getFirstName()
              return firstName;
         public String getLastName()
              return lastName;
         public int getNumYears()
              return numYears;
         public String getSprot()
              return sprot;
         public boolean isVegetarian()
              return vegetarian;
         public void setFirstName(String firstName)
              this.firstName = firstName;
         public void setLastName(String lastName)
              this.lastName = lastName;
         public void setNumYears(int numYears)
              this.numYears = numYears;
         public void setSprot(String sprot)
              this.sprot = sprot;
         public void setVegetarian(boolean vegetarian)
              this.vegetarian = vegetarian;
    }//(3)TableSorter
    package sorter;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import java.util.List;
    import javax.swing.*;
    import javax.swing.event.TableModelEvent;
    import javax.swing.event.TableModelListener;
    import javax.swing.table.*;
    public class TableSorter extends AbstractTableModel {
        protected TableModel tableModel;
        public static final int DESCENDING = -1;
        public static final int NOT_SORTED = 0;
        public static final int ASCENDING = 1;
        private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED);
        public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() {
            public int compare(Object o1, Object o2) {
                return ((Comparable) o1).compareTo(o2);
        public static final Comparator LEXICAL_COMPARATOR = new Comparator() {
            public int compare(Object o1, Object o2) {
                return o1.toString().compareTo(o2.toString());
        private Row[] viewToModel;
        private int[] modelToView;
        private JTableHeader tableHeader;
        private MouseListener mouseListener;
        private TableModelListener tableModelListener;
        private Map columnComparators = new HashMap();
        private List sortingColumns = new ArrayList();
        public TableSorter() {
            this.mouseListener = new MouseHandler();
            this.tableModelListener = new TableModelHandler();
        public TableSorter(TableModel tableModel) {
            this();
            setTableModel(tableModel);
        public TableSorter(TableModel tableModel, JTableHeader tableHeader) {
            this();
            setTableHeader(tableHeader);
            setTableModel(tableModel);
        private void clearSortingState() {
            viewToModel = null;
            modelToView = null;
        public TableModel getTableModel() {
            return tableModel;
        public void setTableModel(TableModel tableModel) {
            if (this.tableModel != null) {
                this.tableModel.removeTableModelListener(tableModelListener);
            this.tableModel = tableModel;
            if (this.tableModel != null) {
                this.tableModel.addTableModelListener(tableModelListener);
            clearSortingState();
            fireTableStructureChanged();
        public JTableHeader getTableHeader() {
            return tableHeader;
        public void setTableHeader(JTableHeader tableHeader) {
            if (this.tableHeader != null) {
                this.tableHeader.removeMouseListener(mouseListener);
                TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer();
                if (defaultRenderer instanceof SortableHeaderRenderer) {
                    this.tableHeader.setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer);
            this.tableHeader = tableHeader;
            if (this.tableHeader != null) {
                this.tableHeader.addMouseListener(mouseListener);
                this.tableHeader.setDefaultRenderer(
                        new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer()));
        public boolean isSorting() {
            return sortingColumns.size() != 0;
        private Directive getDirective(int column) {
            for (int i = 0; i < sortingColumns.size(); i++) {
                Directive directive = (Directive)sortingColumns.get(i);
                if (directive.column == column) {
                    return directive;
            return EMPTY_DIRECTIVE;
        public int getSortingStatus(int column) {
            return getDirective(column).direction;
        private void sortingStatusChanged() {
            clearSortingState();
            fireTableDataChanged();
            if (tableHeader != null) {
                tableHeader.repaint();
        public void setSortingStatus(int column, int status) {
            Directive directive = getDirective(column);
            if (directive != EMPTY_DIRECTIVE) {
                sortingColumns.remove(directive);
            if (status != NOT_SORTED) {
                sortingColumns.add(new Directive(column, status));
            sortingStatusChanged();
        protected Icon getHeaderRendererIcon(int column, int size) {
            Directive directive = getDirective(column);
            if (directive == EMPTY_DIRECTIVE) {
                return null;
            return new Arrow(directive.direction == DESCENDING, size, sortingColumns.indexOf(directive));
        private void cancelSorting() {
            sortingColumns.clear();
            sortingStatusChanged();
        public void setColumnComparator(Class type, Comparator comparator) {
            if (comparator == null) {
                columnComparators.remove(type);
            } else {
                columnComparators.put(type, comparator);
        protected Comparator getComparator(int column) {
            Class columnType = tableModel.getColumnClass(column);
            Comparator comparator = (Comparator) columnComparators.get(columnType);
            if (comparator != null) {
                return comparator;
            if (Comparable.class.isAssignableFrom(columnType)) {
                return COMPARABLE_COMAPRATOR;
            return LEXICAL_COMPARATOR;
        private Row[] getViewToModel() {
            if (viewToModel == null) {
                int tableModelRowCount = tableModel.getRowCount();
                viewToModel = new Row[tableModelRowCount];
                for (int row = 0; row < tableModelRowCount; row++) {
                    viewToModel[row] = new Row(row);
                if (isSorting()) {
                    Arrays.sort(viewToModel);
            return viewToModel;
        public int modelIndex(int viewIndex)
            return getViewToModel()[viewIndex].modelIndex;
        private int[] getModelToView()
            if (modelToView == null) {
                int n = getViewToModel().length;
                modelToView = new int[n];
                for (int i = 0; i < n; i++) {
                    modelToView[modelIndex(i)] = i;
            return modelToView;
        // TableModel interface methods
        public int getRowCount() {
            return (tableModel == null) ? 0 : tableModel.getRowCount();
        public int getColumnCount() {
            return (tableModel == null) ? 0 : tableModel.getColumnCount();
        public String getColumnName(int column) {
            return tableModel.getColumnName(column);
        public Class getColumnClass(int column) {
            return tableModel.getColumnClass(column);
        public boolean isCellEditable(int row, int column) {
            return tableModel.isCellEditable(modelIndex(row), column);
        public Object getValueAt(int row, int column) {
            return tableModel.getValueAt(modelIndex(row), column);
        public void setValueAt(Object aValue, int row, int column) {
            tableModel.setValueAt(aValue, modelIndex(row), column);
        // Helper classes
        private class Row implements Comparable {
            private int modelIndex;
            public Row(int index) {
                this.modelIndex = index;
            public int compareTo(Object o) {
                int row1 = modelIndex;
                int row2 = ((Row) o).modelIndex;
                for (Iterator it = sortingColumns.iterator(); it.hasNext();) {
                    Directive directive = (Directive) it.next();
                    int column = directive.column;
                    Object o1 = tableModel.getValueAt(row1, column);
                    Object o2 = tableModel.getValueAt(row2, column);
                    int comparison = 0;
                    // Define null less than everything, except null.
                    if (o1 == null && o2 == null) {
                        comparison = 0;
                    } else if (o1 == null) {
                        comparison = -1;
                    } else if (o2 == null) {
                        comparison = 1;
                    } else {
                        comparison = getComparator(column).compare(o1, o2);
                    if (comparison != 0) {
                        return directive.direction == DESCENDING ? -comparison : comparison;
                return 0;
        private class TableModelHandler implements TableModelListener {
            public void tableChanged(TableModelEvent e) {
                // If we're not sorting by anything, just pass the event along.            
                if (!isSorting()) {
                    clearSortingState();
                    fireTableChanged(e);
                    return;
                // If the table structure has changed, cancel the sorting; the            
                // sorting columns may have been either moved or deleted from            
                // the model.
                if (e.getFirstRow() == TableModelEvent.HEADER_ROW) {
                    cancelSorting();
                    fireTableChanged(e);
                    return;
                // We can map a cell event through to the view without widening            
                // when the following conditions apply:
                // a) all the changes are on one row (e.getFirstRow() == e.getLastRow()) and,
                // b) all the changes are in one column (column != TableModelEvent.ALL_COLUMNS) and,
                // c) we are not sorting on that column (getSortingStatus(column) == NOT_SORTED) and,
                // d) a reverse lookup will not trigger a sort (modelToView != null)
                // Note: INSERT and DELETE events fail this test as they have column == ALL_COLUMNS.
                // The last check, for (modelToView != null) is to see if modelToView
                // is already allocated. If we don't do this check; sorting can become
                // a performance bottleneck for applications where cells 
                // change rapidly in different parts of the table. If cells
                // change alternately in the sorting column and then outside of            
                // it this class can end up re-sorting on alternate cell updates -
                // which can be a performance problem for large tables. The last
                // clause avoids this problem.
                int column = e.getColumn();
                if (e.getFirstRow() == e.getLastRow()
                        && column != TableModelEvent.ALL_COLUMNS
                        && getSortingStatus(column) == NOT_SORTED
                        && modelToView != null) {
                    int viewIndex = getModelToView()[e.getFirstRow()];
                    fireTableChanged(new TableModelEvent(TableSorter.this,
                                                         viewIndex, viewIndex,
                                                         column, e.getType()));
                    return;
                // Something has happened to the data that may have invalidated the row order.
                clearSortingState();
                fireTableDataChanged();
                return;
        private class MouseHandler extends MouseAdapter {
            public void mouseClicked(MouseEvent e) {
                JTableHeader h = (JTableHeader) e.getSource();
                TableColumnModel columnModel = h.getColumnModel();
                int viewColumn = columnModel.getColumnIndexAtX(e.getX());
                int column = columnModel.getColumn(viewColumn).getModelIndex();
                if (column != -1) {
                    int status = getSortingStatus(column);
                    if (!e.isControlDown()) {
                        cancelSorting();
                    // Cycle the sorting states through {NOT_SORTED, ASCENDING, DESCENDING} or
                    // {NOT_SORTED, DESCENDING, ASCENDING} depending on whether shift is pressed.
                    status = status + (e.isShiftDown() ? -1 : 1);
                    status = (status + 4) % 3 - 1; // signed mod, returning {-1, 0, 1}
                    setSortingStatus(column, status);
        private static class Arrow implements Icon {
            private boolean descending;
            private int size;
            private int priority;
            public Arrow(boolean descending, int size, int priority) {
                this.descending = descending;
                this.size = size;
                this.priority = priority;
            public void paintIcon(Component c, Graphics g, int x, int y) {
                Color color = c == null ? Color.GRAY : c.getBackground();            
                // In a compound sort, make each succesive triangle 20%
                // smaller than the previous one.
                int dx = (int)(size/2*Math.pow(0.8, priority));
                int dy = descending ? dx : -dx;
                // Align icon (roughly) with font baseline.
                y = y + 5*size/6 + (descending ? -dy : 0);
                int shift = descending ? 1 : -1;
                g.translate(x, y);
                // Right diagonal.
                g.setColor(color.darker());
                g.drawLine(dx / 2, dy, 0, 0);
                g.drawLine(dx / 2, dy + shift, 0, shift);
                // Left diagonal.
                g.setColor(color.brighter());
                g.drawLine(dx / 2, dy, dx, 0);
                g.drawLine(dx / 2, dy + shift, dx, shift);
                // Horizontal line.
                if (descending) {
                    g.setColor(color.darker().darker());
                } else {
                    g.setColor(color.brighter().brighter());
                g.drawLine(dx, 0, 0, 0);
                g.setColor(color);
                g.translate(-x, -y);
            public int getIconWidth() {
                return size;
            public int getIconHeight() {
                return size;
        private class SortableHeaderRenderer implements TableCellRenderer {
            private TableCellRenderer tableCellRenderer;
            public SortableHeaderRenderer(TableCellRenderer tableCellRenderer) {
                this.tableCellRenderer = tableCellRenderer;
            public Component getTableCellRendererComponent(JTable table,
                                                           Object value,
                                                           boolean isSelected,
                                                           boolean hasFocus,
                                                           int row,
                                                           int column) {
                Component c = tableCellRenderer.getTableCellRendererComponent(table,
                        value, isSelected, hasFocus, row, column);
                if (c instanceof JLabel) {
                    JLabel l = (JLabel) c;
                    l.setHorizontalTextPosition(JLabel.LEFT);
                    int modelColumn = table.convertColumnIndexToModel(column);
                    l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize()));
                return c;
        private static class Directive {
            private int column;
            private int direction;
            public Directive(int column, int direction) {
                this.column = column;
                this.direction = direction;
    }

    The table listens to the TableModel for changes. Changing the table by adding/removing
    rows or columns has no affect on its table model. If you make changes to the table model
    the table will be notified by its TableModelListener and change its view. So tell
    MyTableModel about the change of data:
    public class TableSorterDemo implements ActionListener
        MyTableModel tableModel;
        public TableSorterDemo()
            defaultListModel = new DefaultListModel();
            init1();
            tableModel = new MyTableModel(defaultListModel);
            TableSorter sorter = new TableSorter(tableModel);
        public void actionPerformed(ActionEvent ae)
            if (ae.getSource()==clickMe)
                defaultListModel.removeAllElements();
                init2();
                tableModel.fireTableStructureChanged();
    }

  • How to display the time in Swing jtable

    I need to display the time in jTable.
    The time is a date field in ORACLE database (connected via
    Oracle Thin drivers).
    Im totally stuck. Please help.
    TIA.

    Thanks for your reply.
    My problem is that I have to display time. This time is a DATE field
    in ORACLE database.
    Im using FORTE (UI). What the jTable display is the DATE (1900-01-01) which is not what I want. I want the time to appear in the jTable (hh.mm.ss a).
    What I did was to use the TO_CHAR function of ORACLE to format the
    date to display the correct time in the VIEW before mapping this view
    to be used as a MODEL by the jTable.
    It works now.
    Much appreciate all your help. Thanks.

  • How To Delete Columns In JTable?

    Hi,
    I created a JTable and added values through DefaultTableModel. I Have JButton to add columns if need. I have another JButton to remove columns by entering the columns header.. eg: If there are three columns like A,B,C, If i need to remove column "C" means. I just click the remove button and enter the column header in the dilaog box eg: "C". and the columns will deleted. It is working properly. but if i add a new column means the removed columns also getting added and the datas are also in that same column. how delete a column and it's data in a single shot.
    How to add network drivers in a save as dialog box. I have using my code in Windows and also in mac os.
    Thanks in Advance
    by,
    Mohan

    One possibility would be to use a DefaultTableModel to store the data but have JTable access it through your own table model which mapped the columns and altered the column count etc..Why go to all that trouble. If you just want to hide a column, then remove the TableColumn from the TableColumnManager.
    The requirement was to remove the data as well.
    Implementing AbstractTableModel is really less hassle than it looks. Generally you only have to override getColumnName, getValueAt, getRowCount, getColumnCount and (usually) getColumnClass.Nobody said it was difficult, by why reimplement everything from scratch? Just extend DTM to add your new functionality.

  • Mapping editor not working with Java 5 classes

    I have a small protoype web service which I wrote using Tomcat/Axis/Spring/Hibernate and using EJB3 annotations for the mappings. I want to port the persistence layer to Toplink.
    I installed Toplink 9.0.4.1 and added the toplink libraries to my project and implemented the DAO and the spring bean defs.
    I opened the mapping editor and created a project. When I try to add classes to it for mapping I get an error that it can't find the classes (even though I selected them from the chooser). I figured it might be that they were compiled with Java 5, so I switched the JRE_HOME in setenv.cmd to my Java 5 JRE. Now I can import the classes and see the attributes but when I click on any of them in the Navigator panel, the editor panel remains blank. If I now try to save, I get:
    java.lang.NullPointerException
         at oracle.toplink.workbench.ui.tools.CheckListModel.getRowCount(CheckListModel.java:119)
         at javax.swing.JTable.checkLeadAnchor(JTable.java:2949)
         at javax.swing.JTable.tableChanged(JTable.java:2993)
         at javax.swing.JTable.setModel(JTable.java:2827)
         at oracle.toplink.workbench.ui.tools.CheckList.initialize(CheckList.java:47)
         at oracle.toplink.workbench.ui.tools.CheckList.<init>(CheckList.java:26)
    It seems that the mapping workbench doesnt work with Java 5. What should I do?

    Ah, I see. I saw another post here stating that must use 10.1.3.

  • Tab and back-tab out of a JTable

    Hi There,
    I have been working for some time on improving the default behaviour of the tab key within editable JTables. It largely works as required now, but I'm stuck on getting back-tab to leave the table if on row 0, col 0. I register tab and back-tab action in the table's ActionMap that looks like this:     
         class TabAction extends AbstractAction {
              public void actionPerformed(ActionEvent e) {
                   if (getRowCount() > 0) {
                        int row = getSelectedRow();
                        int column = getSelectedColumn();
                        if (row < 0 || column < 0) {
                             row = 0;
                             column = 0;
                        do {
                             if (++column >= getColumnCount()) {
                                  row++;
                                  column = 0;
                        } while (row < getRowCount() && ! isCellTabbable(row, column));
                        if (row < getRowCount()) {
                             changeSelection(row, column, false, false);
                        } else {
                             clearSelection();
                             transferFocus();
                   } else {
                        transferFocus();
         class BackTabAction extends AbstractAction {
              public void actionPerformed(ActionEvent e) {
                   if (getRowCount() > 0) {
                        int row = getSelectedRow();
                        int column = getSelectedColumn();
                        if (row < 0 || column < 0) {
                             row = getRowCount() - 1;
                             column = getColumnCount() - 1;
                        do {
                             if (--column < 0) {
                                  row--;
                                  column = getColumnCount() - 1;
                        } while (row >= 0 && ! isCellTabbable(row, column));
                        if (row >= 0) {
                             changeSelection(row, column, false, false);
                        } else {
                             clearSelection();
                             transferFocusBackward();
                             KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
                                // fm.upFocusCycle(BTTTable_Editable.this);                         
                             // fm.focusPreviousComponent(BTTTable_Editable.this);
                   } else {     
                        // transferFocusBackward();
                        // KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
                           // fm.upFocusCycle(BTTTable_Editable.this);                         
                        // fm.focusPreviousComponent(BTTTable_Editable.this);
         }transferFocus() to go to the next screen component works fine - as long as I callsetFocusTraversalPolicyProvider(true); when I create the JTable.
    But the backward traversal just doesn't work - instead it does nothing the first time you press back-tab on row 0 col 0, then if you press it again, focus goes onto the last row/col of the table.
    As an alternative, I thought maybe I could call the Ctrl-back-tab action, but I can't find that registered in the action map - can anyone tell me how ctrl-back-tab is called and whether I can call that code directly?
    Any ideas?
    Thanks,
    Tim

    Where's the rest of your code? What good does posting
    the Actions do if we can't execute your code and see
    how you've installed the Actions on the table? Who
    knows where the mistake is. It may be in the posted
    code or it may be in some other code.Well I assume the Action is registered okay because back-tab within the table works fine, and in fact using a debugger I can see that the focus request code (transferFocusBackward) is being called at the right time. I followed it into that code and it appears that it is picking up the tableCellEditor as the "previous" component which is "why" it isn't working right - not that that helps me to fix it.
    Anyway, just to confirm, here is a complete standalone testcase:import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.awt.KeyboardFocusManager;
    import java.awt.event.ActionEvent;
    import java.awt.event.FocusEvent;
    import java.awt.event.FocusListener;
    import java.awt.event.InputEvent;
    import java.awt.event.KeyEvent;
    import javax.swing.AbstractAction;
    import javax.swing.ActionMap;
    import javax.swing.InputMap;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.JTextField;
    import javax.swing.KeyStroke;
    * <br>
    * <br>
    * Created on 14/11/2005 by Tim Ryan
    public class TabTable extends JTable implements FocusListener {
         protected KeyStroke TAB = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
         protected KeyStroke BACK_TAB = KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
                   InputEvent.SHIFT_DOWN_MASK);
         protected KeyStroke LEFT_ARROW = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
         protected KeyStroke RIGHT_ARROW = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);
         public TabTable(Object[][] rowData, Object[] columnNames) {
              super(rowData, columnNames);
              initialise();
         public TabTable() {
              super();
              initialise();
         private void initialise() {
              addFocusListener(this);
              InputMap inMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
              ActionMap actionMap = getActionMap();
              inMap.put(LEFT_ARROW, "None");
              inMap.put(RIGHT_ARROW, "None");
              actionMap.put(inMap.get(TAB), new TabAction());
              actionMap.put(inMap.get(BACK_TAB), new BackTabAction());
              setCellSelectionEnabled(true);
              putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
              setFocusTraversalPolicyProvider(true);
         public void focusGained(FocusEvent e) {
              if (getRowCount() > 0 && getSelectedRow() < 0) {
                   editCellAt(0, 0);
                   getEditorComponent().requestFocusInWindow();
         public void focusLost(FocusEvent e) {
         public void changeSelection(int row, int column, boolean toggle, boolean extend) {
              super.changeSelection(row, column, toggle, false);
              if (editCellAt(row, column)) {
                   getEditorComponent().requestFocusInWindow();
          * This class handles the back-tab operation on the table.
          * It repeatedly steps the selection backwards until the focus
          * ends up on a cell that is allowable (see <code>isCellTabbable()</code>).
          * If already at the end of the table then focus is transferred out
          * to the previous component on the screen.
         class BackTabAction extends AbstractAction {
              public void actionPerformed(ActionEvent e) {
                   if (getRowCount() > 0) {
                        int row = getSelectedRow();
                        int column = getSelectedColumn();
                        if (row < 0 || column < 0) {
                             row = getRowCount() - 1;
                             column = getColumnCount() - 1;
                        do {
                             if (--column < 0) {
                                  row--;
                                  column = getColumnCount() - 1;
                        } while (row >= 0 && ! isCellTabbable(row, column));
                        if (row >= 0) {
                             changeSelection(row, column, false, false);
                        } else {
                             clearSelection();
                             // transferFocusBackward();
                             KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent();
                   } else {
                        // transferFocusBackward();
                        KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent();
          * This class handles the tab operation on the table.
          * It repeatedly steps the selection forwards until the focus ends
          * up on a cell that is allowable (see <code>isCellTabbable()</code>).
          * If already at the end of the table then focus is transferred out
          * to the next component on the screen.
         class TabAction extends AbstractAction {
              public void actionPerformed(ActionEvent e) {
                   if (getRowCount() > 0) {
                        int row = getSelectedRow();
                        int column = getSelectedColumn();
                        if (row < 0 || column < 0) {
                             row = 0;
                             column = 0;
                        do {
                             if (++column >= getColumnCount()) {
                                  row++;
                                  column = 0;
                        } while (row < getRowCount() && ! isCellTabbable(row, column));
                        if (row < getRowCount()) {
                             changeSelection(row, column, false, false);
                        } else {
                             clearSelection();
                             transferFocus();
                   } else {
                        transferFocus();
          * Some cells can be tabbed to, but are not actually editable.
          * @param row
          * @param column
          * @return
         private boolean isCellTabbable(int row, int column) {
              return (column % 2 == 0);
         public boolean isCellEditable(int row, int column) {
              return (column == 1 || column == 3);
          * @param args
         public static void main(String[] args) {
              JFrame frame = new JFrame("Tables test");
              frame.setName("TablesTest");
              frame.setSize(600, 400);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              JPanel panelMain = new JPanel(new GridBagLayout());
              frame.add(panelMain);
              Object[][] tableData = new Object[2][6];
              Object[] columnHeadings = new Object[] {"H0", "H1", "H2", "H3", "H4", "H5"};
              GridBagConstraints gbc = new GridBagConstraints();
              gbc.anchor = GridBagConstraints.NORTH;
              gbc.insets = new Insets(10, 10, 10, 10);
              JTextField field1 = new JTextField("left", 8);
              field1.setName("left");
              panelMain.add(field1, gbc);
              Dimension tableSize = new Dimension(300, 300);
              BTTTable table3 = new BTTTable_Editable(tableData, columnHeadings);
              table3.setName("Editable");
              JScrollPane scroll3 = new JScrollPane(table3);
              scroll3.setPreferredSize(tableSize);
              panelMain.add(scroll3, gbc);
              JTextField field2 = new JTextField("right", 8);
              field2.setName("right");
              gbc.gridwidth = GridBagConstraints.REMAINDER;
              panelMain.add(field2, gbc);
              frame.setVisible(true);
    }I thought it might be the focusGained() code, but commenting that out makes no difference.
    And here is the code I would use to go to the
    previous component:
    KeyboardFocusManager.getCurrentKeyboardFocusManager().
    focusPreviousComponent();I tried that too, as you can see from my original post. It gives the same answer.
    So the big question is why does the FocusManager think that the "previous" field to the table is an editor component within the table?
    Regards,
    Tim

  • Jtable Update problem .. Please help !!!!!!!!

    Hi ,
    I am trying to get my updated Jtable, stored in a table of database over a previous table ......after updating it via drag n drop ....
    But even after I change the cell position to make the changes ... it still takes up the old value of that cell and not the new one while writing the data in the database table...
    Here is the code .... Please see it and tell me if it is possible :
    package newpackage;
    import java.sql.*;
    import java.util.Vector;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.Dimension;
    import java.text.*;
    import newpackage.ExcelExporter;
    import java.awt.Dimension;
    import javax.swing.border.*;
    import javax.swing.table.*;
    import java.awt.datatransfer.*;
    import java.awt.dnd.*;
    import java.awt.image.*;
    import java.io.*;
    import java.util.*;
    import java.awt.print.*;
    import java.awt.*;
    import java.io.*;
    import java.util.Random.*;
    import javax.swing.*;
    import java.text.*;
    import javax.swing.DefaultCellEditor;
    import javax.swing.JComboBox;
    import javax.swing.JTable;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.TableColumn;
    public class tab7le extends javax.swing.JFrame {
        Vector columnNames = new Vector();
        Vector data = new Vector();
        Connection con;
    Statement stat;
    ResultSet rs;
    int li_cols = 0;
    Vector allRows;
    Vector row;
    Vector newRow;
    Vector colNames;
    String dbColNames[];
    String pkValues[];
    String tableName;
    ResultSetMetaData myM;
    String pKeyCol;
    Vector deletedKeys;
    Vector newRows;
    boolean ibRowNew = false;
    boolean ibRowInserted = false;
        private Map<String, Color> colormap = new HashMap<String, Color>();
        /** Creates new form tab7le */
        public tab7le() {
            populate();
            initComponents();
           public void updateDB(){
                     try{
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
          catch (ClassNotFoundException e){
                System.out.println("Cannot Load Driver!");
          try{
             String url = "jdbc:odbc:FAMS";
             con = DriverManager.getConnection(url);
             stat = con.createStatement();
             rs = stat.executeQuery("Select * from SubAllot");
             deletedKeys = new Vector();
             newRows = new Vector();
             myM = rs.getMetaData();
             tableName = myM.getTableName(1);
             li_cols = myM.getColumnCount();
             dbColNames = new String[li_cols];
             for(int col = 0; col < li_cols; col ++){
                dbColNames[col] = myM.getColumnName(col + 1);
             allRows = new Vector();
             while(rs.next()){
                newRow = new Vector();
                for(int i = 1; i <= li_cols; i++){
                   newRow.addElement(rs.getObject(i));
                } // for
                allRows.addElement(newRow);
             } // while
          catch(SQLException e){
             System.out.println(e.getMessage());
    String updateLine[] = new String[dbColNames.length];
          try{
             DatabaseMetaData dbData = con.getMetaData();
             String catalog;
             // Get the name of all of the columns for this table
             String curCol;
             colNames = new Vector();
             ResultSet rset1 = dbData.getColumns(null,null,tableName,null);
             while (rset1.next()) {
                curCol = rset1.getString(4);
                colNames.addElement(curCol);
             rset1.close();
             pKeyCol = colNames.firstElement().toString();
             // Go through the rows and perform INSERTS/UPDATES/DELETES
             int totalrows;
             totalrows = allRows.size();
             String dbValues[];
             Vector currentRow = new Vector();
             pkValues = new String[allRows.size()];
             // Get column names and values
             for(int i=0;i < totalrows;i++){
                currentRow = (Vector) allRows.elementAt(i);
                int numElements = currentRow.size();
                dbValues = new String[numElements];
                for(int x = 0; x < numElements; x++){
                   String classType = currentRow.elementAt(x).getClass().toString();
                   int pos = classType.indexOf("String");
                   if(pos > 0){ // we have a String
                      dbValues[x] = "'" + currentRow.elementAt(x) + "'";
                      updateLine[x] = dbColNames[x] + " = " + "'" + currentRow.elementAt(x) + "',";
                      if (dbColNames[x].toUpperCase().equals(pKeyCol.toUpperCase())){
                        pkValues[i] = currentRow.elementAt(x).toString() ;
                   pos = classType.indexOf("Integer");
                   if(pos > 0){ // we have an Integer
                      dbValues[x] = currentRow.elementAt(x).toString();
                      if (dbColNames[x].toUpperCase().equals(pKeyCol.toUpperCase())){
                         pkValues[i] = currentRow.elementAt(x).toString();
                      else{
                         updateLine[x] = dbColNames[x] + " = " + currentRow.elementAt(x).toString() + ",";
                   pos = classType.indexOf("Boolean");
                   if(pos > 0){ // we have a Boolean
                      dbValues[x] = currentRow.elementAt(x).toString();
                      updateLine[x] = dbColNames[x] + " = " + currentRow.elementAt(x).toString() + ",";
                      if (dbColNames[x].toUpperCase().equals(pKeyCol.toUpperCase())){
                         pkValues[i] = currentRow.elementAt(x).toString() ;
                } // For Loop
                // If we are here, we have read one entire row of data. Do an UPDATE or an INSERT
                int numNewRows = newRows.size();
                int insertRow = 0;
                boolean newRowFound;
                for (int z = 0;z < numNewRows;z++){
                   insertRow = ((Integer) newRows.get(z)).intValue();
                   if(insertRow == i+1){
                      StringBuffer InsertSQL = new StringBuffer();
                      InsertSQL.append("INSERT INTO " + tableName + " (");
                      for(int zz=0;zz<=dbColNames.length-1;zz++){
                         if (dbColNames[zz] != null){
                            InsertSQL.append(dbColNames[zz] + ",");
                      // Strip out last comma
                      InsertSQL.replace(InsertSQL.length()-1,InsertSQL.length(),")");
                      InsertSQL.append(" VALUES(" + pkValues[i] + ",");
                      for(int c=1;c < dbValues.length;c++){
                         InsertSQL.append(dbValues[c] + ",");
                      InsertSQL.replace(InsertSQL.length()-1,InsertSQL.length(),")");
                      System.out.println(InsertSQL.toString());
                      stat.executeUpdate(InsertSQL.toString());
                      ibRowInserted=true;
                } // End of INSERT Logic
                // If row has not been INSERTED perform an UPDATE
                if(ibRowInserted == false){
                   StringBuffer updateSQL = new StringBuffer();
                   updateSQL.append("UPDATE " + tableName + " SET ");
                   for(int z=0;z<=updateLine.length-1;z++){
                      if (updateLine[z] != null){
                         updateSQL.append(updateLine[z]);
                   // Replace the last ',' in the SQL statement with a blank. Then add WHERE clause
                   updateSQL.replace(updateSQL.length()-1,updateSQL.length()," ");
                   updateSQL.append(" WHERE " + pKeyCol + " = " + pkValues[i] );
                   System.out.println(updateSQL.toString());
                   stat.executeUpdate(updateSQL.toString());
                   } //for
             catch(Exception ex){
                System.out.println("SQL Error! Cannot perform SQL UPDATE " + ex.getMessage());
             // Delete records from the DB
             try{
                int numDeletes = deletedKeys.size();
                String deleteSQL;
                for(int i = 0; i < numDeletes;i++){
                   deleteSQL = "DELETE FROM " + tableName + " WHERE " + pKeyCol + " = " +
                                                ((Integer) deletedKeys.get(i)).toString();
                System.out.println(deleteSQL);
                   stat.executeUpdate(deleteSQL);
                // Assume deletes where successful. Recreate Vector holding PK Keys
                deletedKeys = new Vector();
             catch(Exception ex){
                System.out.println(ex.getMessage());
        public void populate()
            try
                //  Connect to the Database
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                Connection con = DriverManager.getConnection("Jdbc:Odbc:FAMS"," "," ");
                System.out.println("ok1");
                //  Read data from a table
                String sql;
                 sql = "Select * from SubAllot";
                 System.out.println("ok1");
                Statement stmt = con.createStatement();
                System.out.println("ok1");
                ResultSet rs = stmt.executeQuery( sql );
                System.out.println("ok1");
                ResultSetMetaData md = rs.getMetaData();
                System.out.println("ok1");
                int columns = md.getColumnCount();
                for(int i = 0;i<columns;i++){
                    columnNames.addElement(md.getColumnName(i+1));
                    System.out.println("ok2");
                while (rs.next())
                    Vector row = new Vector(columns);
                    for (int i = 1; i <columns+1; i++)
                        row.addElement( rs.getObject(i) );
                    data.addElement( row );
            catch(Exception e){
                e.printStackTrace();
                 public void dropmenu(JTable table,TableColumn subpref1) {
            //Set up the editor for the sport cells.
            JComboBox comboBox = new JComboBox();
          for (int i = 0;i<=20;i++)
           comboBox.addItem(i);
            subpref1.setCellEditor(new DefaultCellEditor(comboBox));
            //Set up tool tips for the sport cells.
            DefaultTableCellRenderer renderer =
                    new DefaultTableCellRenderer();
            renderer.setToolTipText("Click for combo box");
            subpref1.setCellRenderer(renderer);
                       abstract class StringTransferHandler extends TransferHandler {
            public int dropAction;
            protected abstract String exportString(final JComponent c);
            protected abstract void importString(final JComponent c, final String str);
            @Override
            protected Transferable createTransferable(final JComponent c) {
                return new StringSelection(exportString(c));
            @Override
            public int getSourceActions(final JComponent c) {
                return MOVE;
            @Override
            public boolean importData(final JComponent c, final Transferable t) {
                if (canImport(c, t.getTransferDataFlavors())) {
                    try {
                        String str = (String) t.getTransferData(DataFlavor.stringFlavor);
                        importString(c, str);
                        return true;
                    } catch (UnsupportedFlavorException ufe) {
                    } catch (IOException ioe) {
                return false;
            @Override
            public boolean canImport(final JComponent c, final DataFlavor[] flavors) {
                for (int ndx = 0; ndx < flavors.length; ndx++) {
                    if (DataFlavor.stringFlavor.equals(flavors[ndx])) {
                        return true;
                return false;
        class TableTransferHandler extends StringTransferHandler {
            private int dragRow;
            private int[] dragColumns;
            private BufferedImage[] image;
            private int row;
            private int[] columns;
            public JTable target;
            private Map<String, Color> colormap;
            private TableTransferHandler(final Map<String, Color> colormap) {
                this.colormap = colormap;
            @Override
            protected Transferable createTransferable(final JComponent c) {
                JTable table = (JTable) c;
                dragRow = table.getSelectedRow();
                dragColumns = table.getSelectedColumns();
                createDragImage(table);
                return new StringSelection(exportString(c));
            protected String exportString(final JComponent c) {
                JTable table = (JTable) c;
                row = table.getSelectedRow();
                columns = table.getSelectedColumns();
                StringBuffer buff = new StringBuffer();
                colormap.clear();
                for (int j = 0; j < columns.length; j++) {
                    Object val = table.getValueAt(row, columns[j]);
                    buff.append(val == null ? "" : val.toString());
                    if (j != columns.length - 1) {
                        buff.append(",");
                    colormap.put(row+","+columns[j], Color.LIGHT_GRAY);
                table.repaint();
                return buff.toString();
            protected void importString(final JComponent c, final String str) {
                target = (JTable) c;
                DefaultTableModel model = (DefaultTableModel) target.getModel();
                String[] values = str.split("\n");
                int colCount = target.getSelectedColumn();
                int max = target.getColumnCount();
                for (int ndx = 0; ndx < values.length; ndx++) {
                    String[] data = values[ndx].split(",");
                    for (int i = 0; i < data.length; i++) {
                        String string = data;
    if(colCount < max){
    Object val = model.getValueAt(target.getSelectedRow(), colCount);
    model.setValueAt(string, target.getSelectedRow(), colCount);
    model.setValueAt(val, dragRow, dragColumns[i]);
    colCount++;
    public BufferedImage[] getDragImage() {
    return image;
    private void createDragImage(final JTable table) {
    if (dragColumns != null) {
    try {
    image = new BufferedImage[dragColumns.length];
    for (int i = 0; i < dragColumns.length; i++) {
    Rectangle cellBounds = table.getCellRect(dragRow, i, true);
    TableCellRenderer r = table.getCellRenderer(dragRow, i);
    DefaultTableModel m = (DefaultTableModel) table.getModel();
    JComponent lbl = (JComponent) r.getTableCellRendererComponent(table,
    table.getValueAt(dragRow, dragColumns[i]), false, false, dragRow, i);
    lbl.setBounds(cellBounds);
    BufferedImage img = new BufferedImage(lbl.getWidth(), lbl.getHeight(),
    BufferedImage.TYPE_INT_ARGB_PRE);
    Graphics2D graphics = img.createGraphics();
    graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f));
    lbl.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
    lbl.paint(graphics);
    graphics.dispose();
    image[i] = img;
    } catch (RuntimeException re) {
    class TableDropTarget extends DropTarget {
    private Insets autoscrollInsets = new Insets(20, 20, 20, 20);
    private Rectangle rect2D = new Rectangle();
    private TableTransferHandler handler;
    public TableDropTarget(final TableTransferHandler h) {
    super();
    this.handler = h;
    @Override
    public void dragOver(final DropTargetDragEvent dtde) {
    handler.dropAction = dtde.getDropAction();
    JTable table = (JTable) dtde.getDropTargetContext().getComponent();
    Point location = dtde.getLocation();
    int row = table.rowAtPoint(location);
    int column = table.columnAtPoint(location);
    table.changeSelection(row, column, false, false);
    paintImage(table, location);
    autoscroll(table, location);
    super.dragOver(dtde);
    public void dragExit(final DropTargetDragEvent dtde) {
    clearImage((JTable) dtde.getDropTargetContext().getComponent());
    super.dragExit(dtde);
    @Override
    public void drop(final DropTargetDropEvent dtde) {
    Transferable data = dtde.getTransferable();
    JTable table = (JTable) dtde.getDropTargetContext().getComponent();
    clearImage(table);
    handler.importData(table, data);
    super.drop(dtde);
    private final void paintImage(final JTable table, final Point location) {
    Point pt = new Point(location);
    BufferedImage[] image = handler.getDragImage();
    if (image != null) {
    table.paintImmediately(rect2D.getBounds());
    rect2D.setLocation(pt.x - 15, pt.y - 15);
    int wRect2D = 0;
    int hRect2D = 0;
    for (int i = 0; i < image.length; i++) {
    table.getGraphics().drawImage(image[i], pt.x - 15, pt.y - 15, table);
    pt.x += image[i].getWidth();
    if (hRect2D < image[i].getHeight()) {
    hRect2D = image[i].getHeight();
    wRect2D += image[i].getWidth();
    rect2D.setSize(wRect2D, hRect2D);
    private final void clearImage(final JTable table) {
    table.paintImmediately(rect2D.getBounds());
    private Insets getAutoscrollInsets() {
    return autoscrollInsets;
    private void autoscroll(final JTable table, final Point cursorLocation) {
    Insets insets = getAutoscrollInsets();
    Rectangle outer = table.getVisibleRect();
    Rectangle inner = new Rectangle(outer.x + insets.left,
    outer.y + insets.top,
    outer.width - (insets.left + insets.right),
    outer.height - (insets.top + insets.bottom));
    if (!inner.contains(cursorLocation)) {
    Rectangle scrollRect = new Rectangle(cursorLocation.x - insets.left,
    cursorLocation.y - insets.top,
    insets.left + insets.right,
    insets.top + insets.bottom);
    table.scrollRectToVisible(scrollRect);
    /** This method is called from within the constructor to
    * initialize the form.
    * WARNING: Do NOT modify this code. The content of this method is
    * always regenerated by the Form Editor.
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {
    jScrollPane1 = new javax.swing.JScrollPane();
    table = new javax.swing.JTable();
    jButton1 = new javax.swing.JButton();
    jButton2 = new javax.swing.JButton();
    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    table.setModel(new javax.swing.table.DefaultTableModel(
    data, columnNames
    jScrollPane1.setViewportView(table);
    //populate();
    table.getTableHeader().setReorderingAllowed(false);
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    table.setCellSelectionEnabled(true);
    table.setDragEnabled(true);
    TableTransferHandler th = new TableTransferHandler(colormap);
    table.setTransferHandler(th);
    table.setDropTarget(new TableDropTarget(th));
    dropmenu(table, table.getColumnModel().getColumn(11));
    jButton1.setText("Update");
    jButton1.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
    jButton1ActionPerformed(evt);
    jButton2.setText("Ex");
    jButton2.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
    jButton2ActionPerformed(evt);
    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
    .addGap(92, 92, 92)
    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 605, javax.swing.GroupLayout.PREFERRED_SIZE))
    .addGroup(layout.createSequentialGroup()
    .addGap(347, 347, 347)
    .addComponent(jButton1)
    .addGap(115, 115, 115)
    .addComponent(jButton2)))
    .addContainerGap(73, Short.MAX_VALUE))
    layout.setVerticalGroup(
    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
    .addGap(47, 47, 47)
    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 354, javax.swing.GroupLayout.PREFERRED_SIZE)
    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
    .addGap(58, 58, 58)
    .addComponent(jButton1)
    .addContainerGap(83, Short.MAX_VALUE))
    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    .addComponent(jButton2)
    .addGap(65, 65, 65))))
    pack();
    }// </editor-fold>
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                        
    updateDB(); // TODO add your handling code here:
    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                        
    try {
    String pathToDesktop = System.getProperty("user.home")+File.separator+"Desktop";
    pathToDesktop = pathToDesktop + "//Final Allotment.xls";
    ExcelExporter exp = new ExcelExporter();
    exp.exportTable(table, new File(pathToDesktop));
    JOptionPane.showMessageDialog(this,"File exported and saved on desktop!");
    catch (IOException ex) {
    System.out.println(ex.getMessage());
    ex.printStackTrace();
    } // TODO add your handling code here:
    * @param args the command line arguments
    public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
    new tab7le().setVisible(true);
    // Variables declaration - do not modify
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable table;
    // End of variables declaration
    Please help !!!!!!!!
    Thanks in advance.....                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                

    Here is the code Do you expect people to read through 400 lines of code to understand what you are doing?
    Why post code with access to a database? We can't access the database.
    Search the forum for my "Database Information" (without the space) example class which shows you how to refresh a table with new data.
    If you need further help then you need to create a [Short, Self Contained, Compilable and Executable, Example Program (SSCCE)|http://homepage1.nifty.com/algafield/sscce.html], that demonstrates the incorrect behaviour.

  • Combobox in jtable

    suppose you are editing a combobox in a jtable.
    in the combobox, there are items like
    A0
    A20
    C0
    C20
    E0
    E20
    my main goal is traverse and edit the table by keyboard.
    when i go to a jcombobox, e.g. i hit the button C, it only focus the combo, not selecting item.
    JComboBox comboBox = new JComboBox(arr){
                   protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
                        int condition, boolean pressed) {
                    boolean retValue = super.processKeyBinding(ks, e, condition, pressed);
                    if (!retValue && isStartingCellEdit() && editor != null) {
                        //editor.setItem(String.valueOf(ks.getKeyChar()));
                        JComponent editorComponent = (JComponent) getEditor().getEditorComponent();
                        InputMap map = editorComponent.getInputMap(condition);
                        ActionMap am = editorComponent.getActionMap();
                        if(map!=null && am!=null && isEnabled()){
                            Object binding = map.get(ks);
                            Action action = (binding==null) ? null : am.get(binding);
                            if(action!=null){
                                 SwingUtilities.notifyAction(action, ks, e, editorComponent,
                                        e.getModifiers());
                    return retValue;
                private boolean isStartingCellEdit() {
                    JTable table = (JTable) SwingUtilities.getAncestorOfClass(
                            JTable.class, this);
                    return table != null
                            && table.isFocusOwner()
                            && !Boolean.FALSE.equals((Boolean) table
                                    .getClientProperty("JTable.autoStartsEdit"));
    };so if i want to write C20,
    when i pressed C, it selects the combo, so after pressing 2 and 0, it searches for 20.
    how can i do this not to lose the first char?

    suppose you are editing a combobox in a jtable.
    in the combobox, there are items like
    A0
    A20
    C0
    C20
    E0
    E20
    my main goal is traverse and edit the table by keyboard.
    when i go to a jcombobox, e.g. i hit the button C, it only focus the combo, not selecting item.
    JComboBox comboBox = new JComboBox(arr){
                   protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
                        int condition, boolean pressed) {
                    boolean retValue = super.processKeyBinding(ks, e, condition, pressed);
                    if (!retValue && isStartingCellEdit() && editor != null) {
                        //editor.setItem(String.valueOf(ks.getKeyChar()));
                        JComponent editorComponent = (JComponent) getEditor().getEditorComponent();
                        InputMap map = editorComponent.getInputMap(condition);
                        ActionMap am = editorComponent.getActionMap();
                        if(map!=null && am!=null && isEnabled()){
                            Object binding = map.get(ks);
                            Action action = (binding==null) ? null : am.get(binding);
                            if(action!=null){
                                 SwingUtilities.notifyAction(action, ks, e, editorComponent,
                                        e.getModifiers());
                    return retValue;
                private boolean isStartingCellEdit() {
                    JTable table = (JTable) SwingUtilities.getAncestorOfClass(
                            JTable.class, this);
                    return table != null
                            && table.isFocusOwner()
                            && !Boolean.FALSE.equals((Boolean) table
                                    .getClientProperty("JTable.autoStartsEdit"));
    };so if i want to write C20,
    when i pressed C, it selects the combo, so after pressing 2 and 0, it searches for 20.
    how can i do this not to lose the first char?

  • JTable printing problem

    Hi , I have a problem add printing routine for printing to this code.
    Sombody help me.
    I no post all code but my prube no functioned.
    thanks you
    code :
    package com.froses.tablemodels;
    * SimpleDBTable.java
    * A demonstration of using ODBC to read data from an Access database
    * and display the values in a JTable.
    * This file requires that the new.mdb file exists and has been mapped
    * using ODBC to a datastore named 'newdb' with blank username and password.
    * Gordon Branson January 2004
    import javax.swing.*;
    import java.awt.Dimension;
    import java.awt.*;
    import java.awt.event.*;
    import java.sql.*;
    public class SimpleDBTable extends JPanel {
    private boolean DEBUG = true;
    private int rows = 10, cols = 5;
    private String url = "jdbc:odbc:Sego";
    private Connection con;
    private Statement stmt;
    private JButton btnRead, btnDelete, btnWrite, btnClose;
              /* Setup the table column names */
    private String[] columnNames = {"Medico",
    "Descripci�n",
    "Obra social",
    "Items",
    "Codigo"};
              /* declare an Object array large enough to hold the database table */
    private Object[][] data = new Object[rows][cols];
    private JTable table;
    public SimpleDBTable() {
    super(new BorderLayout());
    /* Load ODBC diver */
    try {
    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    } catch(java.lang.ClassNotFoundException e) {
    System.err.print("ClassNotFoundException: ");
    System.err.println(e.getMessage());
              /* create the JTable */
    table = new JTable(data, columnNames);
    table.setPreferredScrollableViewportSize(new Dimension(500, 300));
    /* Now read from the database */
    populateTable();
    if (DEBUG) {
    table.addMouseListener(new MouseAdapter() {
    public void mouseClicked(MouseEvent e) {
    printDebugData();
    //Create the Title Label.
    JLabel title = new JLabel("Database Access in Java");
    title.setFont(new java.awt.Font("Arial", 1, 24));
    title.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
    //Add the label to this panel.
    add("North",title);
    //Create the scroll pane and add the JTable to it.
    JScrollPane scrollPane = new JScrollPane(table);
    //Add the scroll pane to this panel.
    add("Center",scrollPane);
    // Create a button panel with a default layout
    JPanel buttons = new JPanel();
    // Create the buttons
    btnRead = new JButton("Read");
    btnClose = new JButton("Close");
    btnWrite = new JButton("Write");
    btnDelete = new JButton("Delete");
    // Add action listeners
    btnRead.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
    populateTable();
    btnDelete.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
    deleteTable();
    btnWrite.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
    writeTable();
    btnClose.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
    System.exit(0);
    // Add the buttons to the button panel
    buttons.add(btnRead);
    buttons.add(btnWrite);
    buttons.add(btnDelete);
    buttons.add(btnClose);
    // Add the buttons panel to main panel
    add("South",buttons);
    private void populateTable(){
         /* Define the SQL Query to get all data from the database table */
    String query = "SELECT * FROM Datos";
    /* First clear the JTable */
    clearTable();
    /* get a handle for the JTable */
    javax.swing.table.TableModel model = table.getModel();
    int r = 0;
    try {
    /* connect to the database */
    con = DriverManager.getConnection(url, "", "");
    stmt = con.createStatement();
    /* run the Query getting the results into rs */
                   ResultSet rs = stmt.executeQuery(query);
                   while ((rs.next()) && (r<rows)) {
                        /* for each row get the fields
                        note the use of Object - necessary
                        to put the values into the JTable */
                   Object nm = rs.getObject("Medico_solic");
                   Object sup = rs.getObject("Descip_Item");
                   Object pri = rs.getObject("Obra_Social");
                   Object sal = rs.getObject("M�dico_opera");
                   Object tot = rs.getObject("Codigo_estudio");
                   model.setValueAt(nm, r, 0);
                   model.setValueAt(sup, r, 1);
                   model.setValueAt(pri, r, 2);
                   model.setValueAt(sal, r, 3);
                   model.setValueAt(tot, r, 4);
                   r++;
    stmt.close();
    con.close();
    } catch(SQLException ex) {
    System.err.println("SQLException: " + ex.getMessage());
    private void deleteTable(){
         emptyTable();
         clearTable();
    private void emptyTable(){
         /* Define the SQL Query to get all data from the database table */
    String query = "DELETE * FROM COFFEES";
    try {
    /* connect to the database */
    con = DriverManager.getConnection(url, "", "");
    stmt = con.createStatement();
    /* run the Query */
                   stmt.executeUpdate(query);
    stmt.close();
    con.close();
    } catch(SQLException ex) {
    System.err.println("SQLException: " + ex.getMessage());
    /* private void writeTable(){
         /* First clear the table */
    /*      emptyTable();
         PreparedStatement insertRow;// = con.prepareStatement(
         String insertString = "INSERT INTO COFFEES " +
                                  "VALUES (?, ?, ?, ?, ?)";
    int numRows = table.getRowCount();
    javax.swing.table.TableModel model = table.getModel();
    Integer sup, sal, tot;
    Double pri;
    Object o;
    if(DEBUG) System.out.println("\nDoing Write...");
    try {
    /* connect to the database */
    /* con = DriverManager.getConnection(url, "", "");
    insertRow = con.prepareStatement(insertString);
         for (int r=0; r < numRows; r++) {
              if (model.getValueAt(r, 0) != null){
                   insertRow.setString(1, (String) model.getValueAt(r, 0));
                   //o = model.getValueAt(r, 1);
                   if(DEBUG) System.out.println(model.getValueAt(r, 1).toString());
                   sup = new Integer((String) model.getValueAt(r, 1));
                   insertRow.setInt(2, sup.intValue());
                   pri = new Double((String) model.getValueAt(r, 2));
                   insertRow.setDouble(3, pri.doubleValue());
                   sal = new Integer((String) model.getValueAt(r, 3));
                   insertRow.setInt(4, sal.intValue());
                   tot = new Integer((String) model.getValueAt(r, 4));
                   insertRow.setInt(5, tot.intValue());
                   insertRow.executeUpdate();
                   System.out.println("Writing Row " + r);
    insertRow.close();
    con.close();
    } catch(SQLException ex) {
    System.err.println("SQLException: " + ex.getMessage());
    clearTable();
    private void writeTable(){
         /* First clear the table */
         emptyTable();
         Statement insertRow;// = con.prepareStatement(
         String baseString = "INSERT INTO Datos " +
                                  "VALUES ('";
         String insertString;
    int numRows = table.getRowCount();
    javax.swing.table.TableModel model = table.getModel();
    Integer sup, sal, tot;
    Double pri;
    Object o;
    if(DEBUG) System.out.println("\nDoing Write...");
    try {
    /* connect to the database */
    con = DriverManager.getConnection(url, "", "");
         for (int r=0; r < numRows; r++) {
              if (model.getValueAt(r, 0) != null){
                   insertString = baseString + model.getValueAt(r, 0)+"',";
                   insertString = insertString + model.getValueAt(r, 1)+",";
                   insertString = insertString + model.getValueAt(r, 2)+",";
                   insertString = insertString + model.getValueAt(r, 3)+",";
                   insertString = insertString + model.getValueAt(r, 4)+");";
                   if(DEBUG) System.out.println(insertString);
              insertRow = con.createStatement();
                   insertRow.executeUpdate(insertString);
                   System.out.println("Writing Row " + r);
    insertRow.close();
    con.close();
    } catch(SQLException ex) {
    System.err.println("SQLException: " + ex.getMessage());
    clearTable();
    private void clearTable(){
    int numRows = table.getRowCount();
    int numCols = table.getColumnCount();
    javax.swing.table.TableModel model = table.getModel();
    for (int i=0; i < numRows; i++) {
    for (int j=0; j < numCols; j++) {
    model.setValueAt(null, i, j);
    private void printDebugData() {
    int numRows = table.getRowCount();
    int numCols = table.getColumnCount();
    javax.swing.table.TableModel model = table.getModel();
    System.out.println("Value of data: ");
    for (int i=0; i < numRows; i++) {
    System.out.print(" row " + i + ":");
    for (int j=0; j < numCols; j++) {
    System.out.print(" " + model.getValueAt(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() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("SimpleDBTable");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    SimpleDBTable newContentPane = new SimpleDBTable();
    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();
    }

    http://forum.java.sun.com/thread.jspa?threadID=626207

Maybe you are looking for

  • Voice Memos bug?

    Voice Memos on my iPhone 5s, iOS 8.02, spontaneously stops recording twice at 25:44.  Anyone else having this problem where voice Memos spontaneously stops recording?  Sometimes it works fine, sometimes it stops after only a few minutes.  Anyone care

  • How to use many external files?

    Hi, for a single onetime load of a .csv file ,I create a file module,then use the flatfile wizard to specify my file. Now If I have to automatically load all files which are in certain location on Windows Server,how do i achieve this ? All my .csv fi

  • Why can't I log into my itunes and icoud from my iphone?

    Why can't I log into my itunes and icloud from my iphone?

  • Ipad 2 keeps restarting

    Ipad 2 restarting when connected to charger, when not connected it´s dead. It dies before i can reset it, every time it restarts it´s "on" less time. I managed to delete and reset all settings and files but dies before I can configure. When i connect

  • Error in AE

    hi experts, please help me from following error. when i am working with file to rfc. file is picking and both sender and receiver cc's are showing successful but in IE i am getting following error. <?xml version="1.0" encoding="UTF-8" standalone="yes