📄 tablesorter.java
字号:
package com.hand.EFA.CriteriaConsolidation;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
/**
* 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
*/
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;
int[] modelToView;
private JTableHeader tableHeader;
private MouseListener mouseListener;
private TableModelListener tableModelListener;
private Map columnComparators = new HashMap();
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 );
}
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 ) );
}
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 )
{
// MAK 2004-10-15
Row[] r = getViewToModel();
if ( r == null )
return -1;
if ( viewIndex >= r.length )
return -1;
return r[viewIndex].modelIndex;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -