想实现一个排序的JTable,功能已经实现。现在想实现在点击列字段排序后,在该字段后面画出一个三角形。
Graphics g = getTableHeader().getGraphics();
g.fillPolygon(new int[]{signX -10,signX -15,signX -5}, new int[]{5,15,15}, 3);
g.dispose();
可是三角形一闪而逝,请问如何让三角形显示出来呢?

解决方案 »

  1.   

    晕倒,原来JTable有排序方法,忙了半天白忙了不过为什么我的这个三角形不起作用呢?
      

  2.   

    高手回我啊
    我还想实现我这个功能如果用setAutoCreateRowSorter(true)的话,而我重写了getTableCellRendererComponent()将其中的一列用JCheckBox显示,也重写了getTableCellEditorComponent()方法了。现在一点击这个JCheckBox就报错:Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Invalid range
    at javax.swing.DefaultRowSorter.rowsUpdated(DefaultRowSorter.java:879)
    at javax.swing.DefaultRowSorter.rowsUpdated(DefaultRowSorter.java:898)
    at javax.swing.JTable.notifySorter(JTable.java:4201)
    at javax.swing.JTable.sortedTableChanged(JTable.java:4055)
    at javax.swing.JTable.tableChanged(JTable.java:4332)
    at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:280)
    at javax.swing.table.AbstractTableModel.fireTableCellUpdated(AbstractTableModel.java:259)
    at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:650)
    at javax.swing.JTable.setValueAt(JTable.java:2662)
    at javax.swing.JTable.editingStopped(JTable.java:4661)
    at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:125)
    at javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(DefaultCellEditor.java:330)
    at javax.swing.DefaultCellEditor.stopCellEditing(DefaultCellEditor.java:215)
    at javax.swing.DefaultCellEditor$EditorDelegate.actionPerformed(DefaultCellEditor.java:347)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
    at javax.swing.JToggleButton$ToggleButtonModel.setPressed(JToggleButton.java:291)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
    at java.awt.Component.processMouseEvent(Component.java:6038)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
    at java.awt.Component.processEvent(Component.java:5803)
    at java.awt.Container.processEvent(Container.java:2058)
    at java.awt.Component.dispatchEventImpl(Component.java:4410)
    at java.awt.Container.dispatchEventImpl(Container.java:2116)
    at java.awt.Component.dispatchEvent(Component.java:4240)
    at javax.swing.plaf.basic.BasicTableUI$Handler.repostEvent(BasicTableUI.java:924)
    at javax.swing.plaf.basic.BasicTableUI$Handler.mouseReleased(BasicTableUI.java:1138)
    at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:273)
    at java.awt.Component.processMouseEvent(Component.java:6038)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
    at java.awt.Component.processEvent(Component.java:5803)
    at java.awt.Container.processEvent(Container.java:2058)
    at java.awt.Component.dispatchEventImpl(Component.java:4410)
    at java.awt.Container.dispatchEventImpl(Container.java:2116)
    at java.awt.Component.dispatchEvent(Component.java:4240)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
    at java.awt.Container.dispatchEventImpl(Container.java:2102)
    at java.awt.Window.dispatchEventImpl(Window.java:2429)
    at java.awt.Component.dispatchEvent(Component.java:4240)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)  
    没看明白这个错误出在哪?
      

  3.   

    哎,to 3L: 你感觉你的回答有意义吗???
    粘代码了:public class AdvancedJTable extends JTable{
    private boolean allowColumnDrag = true;
    private boolean autoResize = true;
    private boolean allowOrder = true;

    private int selectedColumn = -1;
    private Vector<Vector> rowData = new Vector<Vector>();
    private Vector columnData = new Vector();
    private Map<String,Integer> map = new HashMap<String,Integer>();

    private void init(){
    // this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
    // this.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
    // this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    this.setAllowColumnDrag(this.allowColumnDrag);
    this.setAutoResize(this.autoResize);
    this.setAllowOrder(this.allowOrder);
    // this.getTableHeader().setBackground(new Color(220,180,180));
    /*for(int i=0;i<this.getColumnCount();i++){
    columnData.add(this.getColumnName(i));
    }*/
    for(int j=0;j<this.getRowCount();j++){
    Vector v = new Vector();
    for(int i=0;i<this.getColumnCount();i++){
    // System.out.println(i+"\t"+j);
    v.add(this.getValueAt(j, i));
    }
    rowData.add(v);
    }
    for(int i=0;i<this.getColumnCount();i++){
    map.put(this.getColumnModel().getColumn(i).getIdentifier().toString(), 0);
    }
    }

    /*public AdvancedJTable(){
    super();
    this.init();
    }*/
    /*public AdvancedJTable(boolean allowColumnDrag,boolean autoResize,boolean allowOrder){
    super();
    this.allowColumnDrag = allowColumnDrag;
    this.autoResize = autoResize;
    this.allowOrder = allowOrder;
    this.init();
    }*/
    /*public AdvancedJTable(int numRows,int numColumns){
    super(numRows,numColumns);
    this.init();
    }*/
    public AdvancedJTable(Object[][] rowData,Object[] columns){
    super(rowData,columns);
    this.init();
    }
    public AdvancedJTable(Object[][] rowData,Object[] columns,boolean allowColumnDrag,boolean autoResize,boolean allowOrder){
    super(rowData,columns);
    this.allowColumnDrag = allowColumnDrag;
    this.autoResize = autoResize;
    this.allowOrder = allowOrder;
    this.init();
    }
    /*public AdvancedJTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm){
    super(dm,cm,sm);
    this.init();
    }*/
    public AdvancedJTable(Vector rowData,Vector columnData){
    super(rowData,columnData);
    this.init();
    }
    public AdvancedJTable(TableModel dm){
    super(dm);
    this.init();
    }
    public AdvancedJTable(TableModel dm,boolean allowColumnDrag,boolean autoResize,boolean allowOrder){
    super(dm);
    this.allowColumnDrag = allowColumnDrag;
    this.autoResize = autoResize;
    this.allowOrder = allowOrder;
    this.init();
    }
    /*public AdvancedJTable(TableModel dm,TableColumnModel cm){
    super(dm,cm);
    }*/
    public AdvancedJTable(Vector rowData,Vector columnData,boolean allowColumnDrag,boolean autoResize,boolean allowOrder){
    super(rowData,columnData);
    this.allowColumnDrag = allowColumnDrag;
    this.autoResize = autoResize;
    this.allowOrder = allowOrder;
    this.init();
    }

    @Override
    public void addColumn(TableColumn t){//由於要根據列名來進行排序,因此在addColumn()時要把該columnName加入到map中
    // throw new IllegalStateException("addColumn() is not allowed for AdvancedJTable,commented by Hiway@2011-04-07");
    //注意 addColumn()方法在構造JTable時就被隱含調用到。而且addColumn()調用時會把所有的column都加進去
    // 因此首先clear(),然後手動把所有列加進去,下面的map也一樣
    super.addColumn(t);
    if(this.columnData!=null){//
    this.columnData.clear();
    // System.out.println("執行addColumn");
    for(int i=0;i<this.getColumnCount();i++){
    this.columnData.add(this.getColumnModel().getColumn(i).getHeaderValue());
    }
    }
    if(this.map!=null){
    this.map.clear();
    // System.out.println("執行put");
    for(int i=0;i<this.getColumnCount();i++){
    this.map.put(this.getColumnModel().getColumn(i).getHeaderValue().toString(), 0);
    }
    }
    }
    @Override
    public void updateUI(){
    super.updateUI();
    this.setAutoResize(true);
    System.out.println("updateUI");
    }
    public void setAllowColumnDrag(boolean flag){
    JTableHeader header = this.getTableHeader();
    header.setReorderingAllowed(flag);
    }
    public void setAutoResize(boolean flag){
    if(flag){
    int totalWidth = 0;
    Vector<Integer> vec = new Vector<Integer>();

    JTableHeader header = this.getTableHeader();
    int rowCount = this.getRowCount();
    Enumeration columns = this.getColumnModel().getColumns();
    while(columns.hasMoreElements()){
    TableColumn column = (TableColumn)columns.nextElement();
    int col = header.getColumnModel().getColumnIndex(column.getIdentifier());
    int width = (int)this.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(this, column.getIdentifier(), false, false, -1, col).getPreferredSize().getWidth();
    for(int i=0;i<rowCount;i++){
    int preferedWidth = (int)this.getCellRenderer(i, col).getTableCellRendererComponent(this, this.getValueAt(i, col), false, false, i, col).getPreferredSize().getWidth();
    width = Math.max(width, preferedWidth);
    }
    header.setResizingColumn(column);
    vec.add(width+this.getIntercellSpacing().width);
    totalWidth += width+this.getIntercellSpacing().width;
    column.setWidth(width+this.getIntercellSpacing().width);
    }
    // System.out.println(totalWidth+"\t"+this.getPreferredSize().width);
    if(totalWidth<this.getPreferredSize().width){
    // System.out.println("平均各列寬度");
    for(int i=0;i<this.getColumnCount();i++){
    TableColumn column = this.getColumnModel().getColumn(i);
    header.setResizingColumn(column);
    // System.out.println("======="+this.getPreferredSize().width/this.getColumnCount());
    column.setWidth(vec.get(i)+(this.getPreferredSize().width-totalWidth)/this.getColumnCount());
    }
    }
    }
    }
    public void setAllowOrder(boolean flag){
    if(flag){
    this.getTableHeader().setDefaultRenderer(new DefaultTableCellRenderer(){
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
    JButton jb = new JButton();
    jb.setMargin(new Insets(0,0,0,0));
    jb.setBorderPainted(true);
    jb.setBackground(new Color(230,230,230));
    jb.setText(value.toString());
    return jb;
    }
    });
    this.getTableHeader().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    this.getTableHeader().addMouseListener(new MouseAdapter(){
    @Override 
    public void mouseClicked(MouseEvent e){
    if(e.getClickCount()==2 && getRowCount()>0){
    // System.out.println("雙擊排序");
    // System.out.println("map:"+map);
    if(map.size()==0){
    for(int i=0;i<getColumnCount();i++){
    map.put(getColumnModel().getColumn(i).getHeaderValue().toString(), 0);
    }
    }
    // System.out.println("map:"+map);
    selectedColumn = getColumnModel().getColumnIndexAtX(e.getX());
    String columnName = getColumnModel().getColumn(selectedColumn).getIdentifier().toString();
    // System.out.println(columnData);
    // System.out.println(map);
    map.put(columnName, map.get(columnName).intValue()+1);
    System.out.println("選中的列:"+selectedColumn);
    // System.out.println("map"+map);
    List<ArrayList> data = new ArrayList<ArrayList>();
    for(int i=0;i<getRowCount();i++){
    ArrayList v = new ArrayList();
    for(int j=0;j<getColumnCount();j++){
    v.add(getValueAt(i,j));
    }
    data.add(v);
    }
    // System.out.println("原始表中數據:"+data);
    Collections.sort(data,new MyComparator());//第一次點擊升序排列
    rowData.removeAllElements();
    for(int i=0;i<data.size();i++){
    Vector v = new Vector();
    for(int j=0;j<data.get(i).size();j++){
    v.add(data.get(i).get(j).toString());
    }
    rowData.add(v);
    }
    // System.out.println("排序后:"+rowData);
    if(columnData.size()==0){
    for(int i=0;i<getColumnModel().getColumnCount();i++){
    columnData.add(getColumnModel().getColumn(i).getHeaderValue().toString());
    }
    }
    // System.out.println(rowData.size()+"\t"+columnData.size());
    for(int i=0;i<rowData.size();i++){
    for(int j=0;j<columnData.size();j++){
    setValueAt(rowData.get(i).get(j),i,j);
    }
    }
    int signX = 0;
    for(int i=0;i<=selectedColumn;i++){
    TableColumn column = getColumnModel().getColumn(i);
    signX += column.getWidth();
    }
    Graphics g = getTableHeader().getGraphics();
    g.create().fillPolygon(new int[]{signX -10,signX -15,signX -5}, new int[]{5,15,15}, 3);
    g.dispose();
    repaint();
    }
    }
    });
    // this.setAutoCreateRowSorter(true);
    }

    }
    public void setHeaderBgColor(Color color){
    this.getTableHeader().setBackground(color);
    }
    public void setCellEditor(int col,JComponent comp){

    }

    private class MyComparator implements Comparator{
    public int compare(Object o1, Object o2) {
    ArrayList v1 = (ArrayList) o1;
    ArrayList v2 = (ArrayList) o2;
    // System.out.println("v1"+v1+"\tv2"+v2);
    if(map.get(getColumnModel().getColumn(selectedColumn).getIdentifier().toString())%2==1){
    if(v1.get(selectedColumn).toString().compareTo(v2.get(selectedColumn).toString())>0){
    return 1;
    }
    if(v1.get(selectedColumn).toString().compareTo(v2.get(selectedColumn).toString())<0){
    return -1;
    }
    return 0;
    }else{
    if(v1.get(selectedColumn).toString().compareTo(v2.get(selectedColumn).toString())>0){
    return -1;
    }
    if(v1.get(selectedColumn).toString().compareTo(v2.get(selectedColumn).toString())<0){
    return 1;
    }
    return 0;
    }
    }
    }

    }
    代码有点乱,大家只需要关注在 setAllowOrder()中怎么把三角形显示出来就行了,多谢!!!
      

  4.   


    public static void main(String...args){
    JFrame frame = new JFrame("AdvancedJTable");
    String[][] rowData = new String[][]{{"5","1","7","4"},{"11","0","9","3"}};
    String[] columnData = new String[]{"A","B","C","D"};
    // AdvancedJTable table = new AdvancedJTable(rowData,columnData,true,true,true);
    DefaultTableModel model = new DefaultTableModel(rowData,columnData);
    AdvancedJTable table = new AdvancedJTable(model);
    // System.out.println(table.getModel() instanceof DefaultTableModel);
    model.insertRow(1, new String[]{"J","13","f",""});
    model.addColumn("add1", new String[]{"add2","9","add3"});
    model.addColumn("add1", new String[]{"9","add2","add3"});
    frame.setContentPane(new JScrollPane(table));
    frame.setBounds(new Rectangle(10,10,700,600));
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }测试main
      

  5.   

    so strange 剛才在main()里測試了下,setAutoCreateSorter()是可以正常工作的,但是AdvancedJTable在別的類里面引用就報上面那個錯誤了,暈倒