Java example source code file (DefaultTableModel.java)
This example Java source code file (DefaultTableModel.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
The DefaultTableModel.java Java example source code
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.swing.table;
import java.io.Serializable;
import java.util.Vector;
import java.util.Enumeration;
import javax.swing.event.TableModelEvent;
/**
* This is an implementation of <code>TableModel that
* uses a <code>Vector of Vectors to store the
* cell value objects.
* <p>
* <strong>Warning: DefaultTableModel returns a
* column class of <code>Object. When
* <code>DefaultTableModel is used with a
* <code>TableRowSorter this will result in extensive use of
* <code>toString, which for non-String data types
* is expensive. If you use <code>DefaultTableModel with a
* <code>TableRowSorter you are strongly encouraged to override
* <code>getColumnClass to return the appropriate type.
* <p>
* <strong>Warning:
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans™
* has been added to the <code>java.beans package.
* Please see {@link java.beans.XMLEncoder}.
*
* @author Philip Milne
*
* @see TableModel
* @see #getDataVector
*/
public class DefaultTableModel extends AbstractTableModel implements Serializable {
//
// Instance Variables
//
/**
* The <code>Vector of Vectors of
* <code>Object values.
*/
protected Vector dataVector;
/** The <code>Vector of column identifiers. */
protected Vector columnIdentifiers;
//
// Constructors
//
/**
* Constructs a default <code>DefaultTableModel
* which is a table of zero columns and zero rows.
*/
public DefaultTableModel() {
this(0, 0);
}
private static Vector newVector(int size) {
Vector v = new Vector(size);
v.setSize(size);
return v;
}
/**
* Constructs a <code>DefaultTableModel with
* <code>rowCount and columnCount of
* <code>null object values.
*
* @param rowCount the number of rows the table holds
* @param columnCount the number of columns the table holds
*
* @see #setValueAt
*/
public DefaultTableModel(int rowCount, int columnCount) {
this(newVector(columnCount), rowCount);
}
/**
* Constructs a <code>DefaultTableModel with as many columns
* as there are elements in <code>columnNames
* and <code>rowCount of null
* object values. Each column's name will be taken from
* the <code>columnNames vector.
*
* @param columnNames <code>vector containing the names
* of the new columns; if this is
* <code>null then the model has no columns
* @param rowCount the number of rows the table holds
* @see #setDataVector
* @see #setValueAt
*/
public DefaultTableModel(Vector columnNames, int rowCount) {
setDataVector(newVector(rowCount), columnNames);
}
/**
* Constructs a <code>DefaultTableModel with as many
* columns as there are elements in <code>columnNames
* and <code>rowCount of null
* object values. Each column's name will be taken from
* the <code>columnNames array.
*
* @param columnNames <code>array containing the names
* of the new columns; if this is
* <code>null then the model has no columns
* @param rowCount the number of rows the table holds
* @see #setDataVector
* @see #setValueAt
*/
public DefaultTableModel(Object[] columnNames, int rowCount) {
this(convertToVector(columnNames), rowCount);
}
/**
* Constructs a <code>DefaultTableModel and initializes the table
* by passing <code>data and columnNames
* to the <code>setDataVector method.
*
* @param data the data of the table, a <code>Vector
* of <code>Vectors of Object
* values
* @param columnNames <code>vector containing the names
* of the new columns
* @see #getDataVector
* @see #setDataVector
*/
public DefaultTableModel(Vector data, Vector columnNames) {
setDataVector(data, columnNames);
}
/**
* Constructs a <code>DefaultTableModel and initializes the table
* by passing <code>data and columnNames
* to the <code>setDataVector
* method. The first index in the <code>Object[][] array is
* the row index and the second is the column index.
*
* @param data the data of the table
* @param columnNames the names of the columns
* @see #getDataVector
* @see #setDataVector
*/
public DefaultTableModel(Object[][] data, Object[] columnNames) {
setDataVector(data, columnNames);
}
/**
* Returns the <code>Vector of Vectors
* 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);
*
* @return the vector of vectors containing the tables data values
*
* @see #newDataAvailable
* @see #newRowsAdded
* @see #setDataVector
*/
public Vector getDataVector() {
return dataVector;
}
private static Vector nonNullVector(Vector v) {
return (v != null) ? v : new Vector();
}
/**
* Replaces the current <code>dataVector instance variable
* with the new <code>Vector of rows, dataVector.
* Each row is represented in <code>dataVector as a
* <code>Vector of Object values.
* <code>columnIdentifiers are the names of the new
* columns. The first name in <code>columnIdentifiers is
* mapped to column 0 in <code>dataVector. Each row in
* <code>dataVector is adjusted to match the number of
* columns in <code>columnIdentifiers
* either by truncating the <code>Vector if it is too long,
* or adding <code>null values if it is too short.
* <p>Note that passing in a null value for
* <code>dataVector results in unspecified behavior,
* an possibly an exception.
*
* @param dataVector the new data vector
* @param columnIdentifiers the names of the columns
* @see #getDataVector
*/
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 instance
* variable with the values in the array <code>dataVector.
* The first index in the <code>Object[][]
* array is the row index and the second is the column index.
* <code>columnIdentifiers are the names of the new columns.
*
* @param dataVector the new data vector
* @param columnIdentifiers the names of the columns
* @see #setDataVector(Vector, Vector)
*/
public void setDataVector(Object[][] dataVector, Object[] columnIdentifiers) {
setDataVector(convertToVector(dataVector), convertToVector(columnIdentifiers));
}
/**
* Equivalent to <code>fireTableChanged.
*
* @param event the change event
*
*/
public void newDataAvailable(TableModelEvent event) {
fireTableChanged(event);
}
//
// Manipulating rows
//
private void justifyRows(int from, int to) {
// Sometimes the DefaultTableModel 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 method in
* <code>Vector which truncates vectors
* which are too long, and appends <code>nulls if they
* are too short.
* This method also sends out a <code>tableChanged
* notification message to all the listeners.
*
* @param e this <code>TableModelEvent describes
* where the rows were added.
* If <code>null it assumes
* all the rows were newly added
* @see #getDataVector
*/
public void newRowsAdded(TableModelEvent e) {
justifyRows(e.getFirstRow(), e.getLastRow() + 1);
fireTableChanged(e);
}
/**
* Equivalent to <code>fireTableChanged.
*
* @param event the change event
*
*/
public void rowsRemoved(TableModelEvent event) {
fireTableChanged(event);
}
/**
* Obsolete as of Java 2 platform v1.3. Please use <code>setRowCount 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 and greater are discarded.
*
* @param rowCount the new number of rows
* @see #setRowCount
*/
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 and greater are discarded.
*
* @see #setColumnCount
* @since 1.3
*/
public void setRowCount(int rowCount) {
setNumRows(rowCount);
}
/**
* Adds a row to the end of the model. The new row will contain
* <code>null values unless rowData 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 values unless rowData 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 in the model. The new row
* will contain <code>null values unless rowData
* 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 in the model. The new row
* will contain <code>null values unless rowData
* 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 inclusive range <code>start to
* <code>end to the to position in the model.
* After the move, the row that was at index <code>start
* will be at index <code>to.
* This method will send a <code>tableChanged notification
message to all the listeners.
*
* <pre>
* Examples of moves:
*
* 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
*
* 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
* </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 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>newIdentifiers 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>newIdentifiers is less than the current
* number of columns, all the extra columns at the end of a row are
* discarded.
*
* @param columnIdentifiers vector of column identifiers. If
* <code>null, set the model
* to zero columns
* @see #setNumRows
*/
public void setColumnIdentifiers(Vector columnIdentifiers) {
setDataVector(dataVector, columnIdentifiers);
}
/**
* Replaces the column identifiers in the model. If the number of
* <code>newIdentifiers 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>newIdentifiers is less than the current
* number of columns, all the extra columns at the end of a row are
* discarded.
*
* @param newIdentifiers array of column identifiers.
* If <code>null, set
* the model to zero columns
* @see #setNumRows
*/
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 cell values.
* If the new size is less than the current size, all columns at index
* <code>columnCount and greater are discarded.
*
* @param columnCount the new number of columns in the model
*
* @see #setColumnCount
* @since 1.3
*/
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, which may be null. This method
* will send a
* <code>tableChanged notification message to all the listeners.
* This method is a cover for <code>addColumn(Object, Vector) which
* uses <code>null 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, which may be null.
* <code>columnData is the
* optional vector of data for the column. If it is <code>null
* the column is filled with <code>null 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 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. columnData is the
* optional array of data for the column. If it is <code>null
* the column is filled with <code>null 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 notification message to all the listeners.
*
* @see #addColumn(Object, Vector)
*/
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.
* If <code>columnIdentifiers 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() && (column >= 0)) {
id = columnIdentifiers.elementAt(column);
}
return (id == null) ? super.getColumnName(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
* @see #setValueAt
*/
public boolean isCellEditable(int row, int column) {
return true;
}
/**
* Returns an attribute value for the cell at <code>row
* and <code>column.
*
* @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 and
* <code>row. aValue is the new value. This method
* will generate a <code>tableChanged 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 is null,
* returns <code>null
*/
protected static Vector convertToVector(Object[] anArray) {
if (anArray == null) {
return null;
}
Vector<Object> v = new Vector
Other Java examples (source code examples)
Here is a short list of links related to this Java DefaultTableModel.java source code file: