swing表格的列排序
使用JTable实现的表格并没有实现根据指定列排序的功能,但开发者可以利用AbstractTableModel类来实现该功能。由于TableModel不强制要求保存表格里的数据,只要TableModel实现了getValueAt()、getColumnCount()和 getRowCount()三个方法,JTable就可以根据该TableModel生成表格。因此可以创建个SortableTableModel实现类,它可以将原TableModel包装起来,并实现根据指定列排序的功能
程序创建的SortableTableModel实现类会对原TableModel进行包装,但它实际上并不保存任何数据,它会把所有的方法实现委托给原TableModel完成。SortableTableModel仅保存原TableModel里每行的行索引,当程序对SortableTableModel的指定列排序时,实际上仅仅对SortableTableModel里的行索引进排序一一这样造成的结果是: SortableTableModel里的数据行的行索引与原TableModel里数据行的行索引不一致,所以对于TableModel的那些涉及行索引的方法都需要进行相应的转换。下面程序实现了SortableTableModel类,并使用该类来实现对表格根据指定列排序的功能
swing表格的列排序_练习
xxxxxxxxxx
package ch30;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
//由于我们在18行对列头添加了双击事件,所以在运行代码时我们要点击列头,例如点击姓名、年龄、性别
public class a_36_0swing_表格_实现列排序 {
JFrame jf = new JFrame("可按照列排序的表格");
//定义二维数组作为表格数据
Object[][] tableData = {
new Object[]{"张三", 18, "男"},
new Object[]{"李四", 17, "男"},
new Object[]{"小华", 19, "女"},
new Object[]{"小红", 16, "女"},
new Object[]{"王五", 15, "男"},
};
//定义一个一维数组,作为列标题
Object[] columnTitle = {"姓名", "年龄", "性别"};
JTable table = new JTable(tableData, columnTitle);
//将原表格里面的TableModel封装成SortTableModel对象
SortTableModel sorterModel = new SortTableModel(table.getModel());
public void init() {
//使用包装后的SortTableModel对象作为JTable的model对象
table.setModel(sorterModel);
//为每一列的列头增加鼠标监听器
table.getTableHeader().addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
//找出鼠标双击事件所在列的索引
int tableColumn = table.columnAtPoint(e.getPoint());
//将JTable中的列索引,转换成对应的TableModel中的列索引
int modelColumn = table.convertColumnIndexToModel(tableColumn);
//根据指定列进行排序
sorterModel.sort(modelColumn);
}
});
jf.add(new JScrollPane(table));
jf.pack();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
public static void main(String[] args) {
new a_36_0swing_表格_实现列排序().init();
}
//自定义SortTableModel,增强原有的TableModel
class SortTableModel extends AbstractTableModel {
private TableModel model;
private int sortColumn;
private Row[] rows;
public SortTableModel(TableModel model) {
this.model = model;
rows = new Row[model.getRowCount()];
//将原TableModel中的每行记录的索引用Row数组保存起来
for (int i = 0; i < rows.length; i++) {
rows[i] = new Row(i);
}
}
//实现根据指定列进行排序
public void sort(int c) {
sortColumn = c;
Arrays.sort(rows);
//触发数据改变的事件
fireTableDataChanged();
}
//下面3个方法需要访问model中的数据,所以涉及本model中数据和被封装model数据中的索引转换,程序使用rows完成这种转换
public Object getValueAt(int rowIndex, int columnIndex) {
return model.getValueAt(rows[rowIndex].index, columnIndex);
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return isCellEditable(rows[rowIndex].index, columnIndex);
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
model.setValueAt(aValue, rows[rowIndex].index, columnIndex);
}
//下面方法的实现把该model的方法委托给原封装的model来实现
public int getRowCount() {
return model.getRowCount();
}
public int getColumnCount() {
return model.getColumnCount();
}
public String getColumnName(int column) {
return model.getColumnName(column);
}
public Class<?> getColumnClass(int columnIndex) {
return model.getColumnClass(columnIndex);
}
private class Row implements Comparable<Row> {
//该index保存着被封装Model里每行记录的索引
public int index;
public Row(int index) {
this.index = index;
}
//实现两行之间大小的比较
public int compareTo(Row o) {
Object a = model.getValueAt(index, sortColumn);
Object b = model.getValueAt(o.index, sortColumn);
if (a instanceof Comparable) {
return ((Comparable) a).compareTo(b);
} else {
return a.toString().compareTo(b.toString());
}
}
}
}
}