swing表格的列排序
使用JTable实现的表格并没有实现根据指定列排序的功能,但开发者可以利用AbstractTableModel类来实现该功能。由于TableModel不强制要求保存表格里的数据,只要TableModel实现了getValueAt()、getColumnCount()和 getRowCount()三个方法,JTable就可以根据该TableModel生成表格。因此可以创建个SortableTableModel实现类,它可以将原TableModel包装起来,并实现根据指定列排序的功能
程序创建的SortableTableModel实现类会对原TableModel进行包装,但它实际上并不保存任何数据,它会把所有的方法实现委托给原TableModel完成。SortableTableModel仅保存原TableModel里每行的行索引,当程序对SortableTableModel的指定列排序时,实际上仅仅对SortableTableModel里的行索引进排序一一这样造成的结果是: SortableTableModel里的数据行的行索引与原TableModel里数据行的行索引不一致,所以对于TableModel的那些涉及行索引的方法都需要进行相应的转换。下面程序实现了SortableTableModel类,并使用该类来实现对表格根据指定列排序的功能
swing表格的列排序_练习
xxxxxxxxxxpackage 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()); } } } }}