>
업데이트

JobClass에서 열로 지정된 객체를 숫자로 지정할 수없는 버그로 확인되었습니다. Double (버그 ID : 7051636) 입니다. 이에 대해 투표하거나 대안 (더 나은) 해결 방법이있는 경우 의견을 보고서에 게시하십시오.

<시간>

확장 된 AbstractTableModel을 빌드 한 커스텀 테이블 모델로 JTable을 만들고 있습니다. 모델에서 빈 행을 표시하고 정렬하려면 지원해야합니다. 그래서 나는 이것을 구현하기 위해 포스트 를 작성했습니다. 꽤 잘 작동합니다.

JTable에서 필드를 포맷하는 동안 여전히 문제가 있습니다. 다음과 같은 모델이 있다고 가정합니다.

public class MyModel extends AbstractTableModel{
    public Object[] types= {new Integer(0), ""};
    public static final Object EMPTY_ROW = "";
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
         return this.EMPTY_ROW;
    }
    public Class<? extends Object> getColumnClass(int c) {
      if (c > this.types.length - 1)
        return null;
      else
        return this.types[c].getClass();
    }
}

모든 것이 잘 작동합니다. 그러나 정수 대신 Double이있는 경우 :

public class MyModel extends AbstractTableModel{
        public Object[] types= {new Double(0.0), ""};
  .......

잘못된 인수 예외가 발생합니다 :

수정 : @Aaron Digulla 제안 후 새 스택 추적 출력

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Cannot format given Object as a Number at java.text.DecimalFormat.format(DecimalFormat.java:487) at java.text.Format.format(Format.java:140) at javax.swing.JTable$DoubleRenderer.setValue(JTable.java:5352) at javax.swing.table.DefaultTableCellRenderer.getTableCellRendererComponent(DefaultTableCellRenderer.java:237) at javax.swing.JTable.prepareRenderer(JTable.java:5720) at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2072) at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1974) at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1770) at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143) at javax.swing.JComponent.paintComponent(JComponent.java:752) at javax.swing.JComponent.paint(JComponent.java:1029) at javax.swing.JComponent.paintChildren(JComponent.java:862) at javax.swing.JComponent.paint(JComponent.java:1038) at javax.swing.JViewport.paint(JViewport.java:747) at javax.swing.JComponent.paintChildren(JComponent.java:862) at javax.swing.JComponent.paint(JComponent.java:1038) at javax.swing.JComponent.paintChildren(JComponent.java:862) at javax.swing.JComponent.paint(JComponent.java:1038) at javax.swing.JComponent.paintChildren(JComponent.java:862) at javax.swing.JComponent.paint(JComponent.java:1038) at javax.swing.JLayeredPane.paint(JLayeredPane.java:567) at javax.swing.JComponent.paintChildren(JComponent.java:862) at javax.swing.JComponent.paintToOffscreen(JComponent.java:5131) at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:278) at javax.swing.RepaintManager.paint(RepaintManager.java:1224) at javax.swing.JComponent.paint(JComponent.java:1015) at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21) at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60) at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97) at java.awt.Container.paint(Container.java:1780) at java.awt.Window.paint(Window.java:3375) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:796) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:713) at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:693) at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:125) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

이 이유는 무엇인가요?

getValueAt는 모든 테이블 항목을 채우기 위해 항상 같은 값을 반환합니다. 이것은 디버그 전용입니다.

@Override
    public Object getValueAt(int rowIndex, int columnIndex) {
         return this.EMPTY_ROW;
    }

예를 들어 다음과 같이 변경 한 경우 :

@Override
    public Object getValueAt(int rowIndex, int columnIndex) {
         return new Integer(3);
         //or return new Double(3.3);
         //return new String("foobar"); doesn't work
    }

테이블의 일부 필드가 문자열 인 경우에도 모두 제대로 작동합니다. 그것은 나에게 제안 Integer와 Double은 String으로 변환 될 수 있지만 문제는 발생하지 않습니다. 어쨌든 더블 필드에서는 작동하지 않지만 내 EMPTY_ROW와 같은 일반 객체가 선언 된 정수 필드의 값으로 허용 될 수있는 이유를 이해하고 싶습니다.

EDIT2 :

테이블 모델에서 getClass 메소드를 제거하는 경우 작동합니다. 어쨌든 나는 사용자 정의 렌더링 메소드를 구현하도록 강요하더라도 해당 메소드를 제거하지 않고도이 문제를 해결하고 싶습니다.

EDIT3 :

여기에 SSCCE가 있습니다. 테이블에 새 값을 추가하는 동안 오류가 발생하지만 렌더링 문제와 관련이 없습니다.

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Comparator;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SortOrder;
import javax.swing.RowSorter.SortKey;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;

public class TableExample extends JFrame{
    public static final  Object EMPTY_ROW = "";
    public class EmptyRowComparator<COLUMN_TYPE extends Comparable<COLUMN_TYPE>> implements Comparator<Object>{//extends RuleBasedCollator{
        private TableRowSorter<? extends AbstractTableMod> sorter;
    private int column;
        public EmptyRowComparator(TableRowSorter<? extends AbstractTableMod> sorter, int col) throws ParseException {
        //  super(arg0);
            this.sorter = sorter;
            this.column = col;
            // TODO Auto-generated constructor stub
        }

         private int getSortOrder() {
             SortOrder order = SortOrder.ASCENDING;
//           List<? extends SortKey> keys = sorter.getSortKeys();
//           sorter.getSortKeys();
//       
             for (SortKey sortKey : sorter.getSortKeys()) {
                 if (sortKey.getColumn() == this.column) {
                     order = sortKey.getSortOrder();
                     break;
                 }
             }
             return order == SortOrder.ASCENDING ? 1 : -1;
         }

        @Override
        public int hashCode() {
            // TODO Auto-generated method stub
            return 0;
        }
        @Override
        public int compare(Object arg0, Object arg1) {
            // TODO Auto-generated method stub
            //System.out.println("Comparing Integer arg0 " + arg0 + " arg1 " + arg1);
            boolean empty1 = arg0 == EMPTY_ROW;
            boolean empty2 = arg1 == EMPTY_ROW;
            if (empty1 && empty2) {
                return 0;
            }
            else if (empty1) {
                return 1 * getSortOrder();
            }
            else if (empty2) {
                return -1 * getSortOrder();
            }
            return ((Comparable<COLUMN_TYPE>) (COLUMN_TYPE)arg0).compareTo((COLUMN_TYPE)arg1);
        //  return 0;
        }
    }
    public class ConcreteTable extends AbstractTableMod{
        //
        private static final long serialVersionUID = 4672561280810649603L;
        private String[] columnNames = {"ID",
                                        "description"};

        Class[] types = {Integer.class, String.class};
        //Object[] types = {Double.class, String.class};
        private int minimumDisplayedRow;

        public ConcreteTable(){
            //System.out.println("DEBUG ARRAY length " + data.length);
            this.minimumDisplayedRow = 10;
            this.datas = new ArrayList<ArrayList<Object>>();
            for (int i = 0 ; i < this.minimumDisplayedRow  ; i++){
                this.addEmptyRow();
            }
            for (int i = 0 ; i < 5 ; i++){
                ArrayList<Object> row = new ArrayList<Object>();
                row.add(new Integer(i));
                row.add(new String("prova " + i));
                this.addRow(row);
            }
        }

        public String getColumnName(int col) {
            System.out.println("getColumnName " + col + " = " + columnNames[col]);
            return columnNames[col];
        }
        @Override
        protected Class[] getTypeArray() {
            // TODO Auto-generated method stub
            return this.types;
        }
        @Override
        protected ArrayList<Integer> getKeysColumnIndex() {
            // TODO Auto-generated method stub
            ArrayList<Integer> keys = new ArrayList<Integer>();
            keys.add(0);
            return keys;
        }
        public boolean isCellEditable(int row, int col) {
            System.out.println("isCellEditable row " + row + " col " + col);
            if (col == 1){
                System.out.println("TRUE");
                return true;
            }
            return false;
        }
        /*note: generated keys must be in the same order they appear in the table*/
        @Override
        protected Object getGeneratedKeys(int col) {
            // TODO Auto-generated method stub
            if (col != 0 )
                return null;
            return new Integer(this.rowNumber);
        }
        @Override
        protected int getMinimumDisplayedRow() {
            // TODO Auto-generated method stub
            return this.minimumDisplayedRow;
        }

    }
    public abstract class AbstractTableMod extends AbstractTableModel {

        ArrayList<ArrayList<Object>> datas ;
        protected int rowNumber = 0;
        protected abstract Class[] getTypeArray();
        protected abstract ArrayList<Integer> getKeysColumnIndex();
        protected abstract Object getGeneratedKeys(int col);
        protected abstract int getMinimumDisplayedRow();
        public int getRowCount(){
            return this.datas.size() ;
        }
        @Override
        public int getColumnCount() {
            return this.getTypeArray().length;
        }
        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            if (rowIndex >= this.rowNumber ){
                return EMPTY_ROW;
            }
            try{
                ArrayList<Object> row = this.datas.get(rowIndex);
                if (row == null)
                    return null;
                Object obj = row.get(columnIndex);
                return obj;
            }catch(IndexOutOfBoundsException e){
                return null;
            }

        }
        public void setValueAt(Object value, int row, int col) {
            //System.out.println("setValueAt object : " + value.getClass().getName());
            Class<? extends Object> targetColClass = this.getColumnClass(col);
            if (!targetColClass.isInstance(value))
                return;
            if (value instanceof String){
                String stringVal = (String)value;
                if (stringVal.compareTo("") == 0)
                    return;
            }
            if (row >= this.rowNumber){
                ArrayList<Object> newRow = new ArrayList<Object>();
                ArrayList<Integer> keysIndexList = this.getKeysColumnIndex();
                for (int i = 0 ; i < this.getColumnCount(); i++){
                    if (i == col){
                        newRow.add(value);
                    }else if (keysIndexList.contains(i)){
                        newRow.add(this.getGeneratedKeys(i));
                    }else{
                        newRow.add(EMPTY_ROW);
                    }
                }
                this.addRow(newRow);
            }else{
                this.datas.get(row).set(col, value);
            }
            this.fireTableCellUpdated(row, col);
        }
        public Class<? extends Object> getColumnClass(int c) {
            System.out.println("AbstractTable: getColumnClass");
            if (c > this.getTypeArray().length - 1)
                return null;
            else
                return this.getTypeArray()[c];
        }
        public void addEmptyRow(){
            ArrayList<Object> emptyRow = new ArrayList<Object>();
            for (int i = 0 ; i < this.getTypeArray().length; i++){
                emptyRow.add(EMPTY_ROW);
            }
            this.datas.add(emptyRow);
        }
        public void addRow(ArrayList<Object> row){
            Object[] types = this.getTypeArray();
            if (types.length != row.size())
                return;
            for (int i = 0 ; i < row.size() ; i++){
                Class<? extends Object> targetColClass = this.getColumnClass(i);
                Object rowItem = row.get(i);
            }
            this.datas.add(this.rowNumber, row);
            this.rowNumber++;
            if (this.rowNumber < this.getMinimumDisplayedRow())
                this.datas.remove(this.datas.size() -1 );
            this.fireTableRowsInserted(this.rowNumber , this.rowNumber  );
        }
    }
    public TableExample(){
        super("JTable example");
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));

        ConcreteTable model = new ConcreteTable();
        JTable tab = new JTable(model);
        TableRowSorter<ConcreteTable> sorter = new TableRowSorter<ConcreteTable>(model);

        try {
            sorter.setComparator(0, new EmptyRowComparator<Integer>(sorter,0));
            sorter.setComparator(1, new EmptyRowComparator<String>(sorter,1));
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        tab.setRowSorter(sorter);
        JScrollPane table = new JScrollPane(tab);
        this.getContentPane().add(table);
        this.setSize(600, 400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
            new TableExample();
    }
}

변경하려는 경우

Class[] types = {Integer.class, String.class};

with :

Class[] types = {Double.class, String.class};

문제를 볼 수 있습니다.


  • 답변 # 1

    Walter Laan 어떻게  그의 실에서 말한다

    Never give up! Never surrender!
    
    

    편집 : 저항 할 수는 없지만 내 영어 실력이 떨어지기 때문에 TableColumnRendering에 대해 Rob의 두 가지 (작은 비트) 수정 클래스를 추가 한 이유, 장소 및 방법이 가능하고 올바르게 작동하는지 언급하지 않습니다. ..,

    import java.awt.EventQueue;
    import java.math.RoundingMode;
    import java.text.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.RowSorter.SortKey;
    import javax.swing.SwingConstants;
    import javax.swing.table.*;
    public class TableExample extends JFrame {
        public static final Object EMPTY_ROW = "";
        private static final long serialVersionUID = 1L;
        private JTable tab;
        private Calendar cal;
        private Date dateWithOutTime = new java.util.Date();
        private SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");//standard continental EU date format
        public class EmptyRowComparator<COLUMN_TYPE extends Comparable<COLUMN_TYPE>> implements Comparator<Object> {//extends RuleBasedCollator{
            private TableRowSorter<? extends AbstractTableMod> sorter;
            private int column;
            public EmptyRowComparator(TableRowSorter<? extends AbstractTableMod> sorter, int col) throws ParseException {
                this.sorter = sorter;
                this.column = col;
            }
            private int getSortOrder() {
                SortOrder order = SortOrder.ASCENDING;
                for (SortKey sortKey : sorter.getSortKeys()) {
                    if (sortKey.getColumn() == this.column) {
                        order = sortKey.getSortOrder();
                        break;
                    }
                }
                return order == SortOrder.ASCENDING ? 1 : -1;
            }
            @Override
            public int hashCode() {
                return 0;
            }
            @Override
            @SuppressWarnings("unchecked")
            public int compare(Object arg0, Object arg1) {
                boolean empty1 = arg0 == EMPTY_ROW;
                boolean empty2 = arg1 == EMPTY_ROW;
                if (empty1 && empty2) {
                    return 0;
                } else if (empty1) {
                    return 1 * getSortOrder();
                } else if (empty2) {
                    return -1 * getSortOrder();
                }
                return ((Comparable<COLUMN_TYPE>) (COLUMN_TYPE) arg0).compareTo((COLUMN_TYPE) arg1);
            }
        }
        public class ConcreteTable extends AbstractTableMod {
            private static final long serialVersionUID = 4672561280810649603L;
            private String[] columnNames = {"Integer", "String", "Integer", "Double", "Boolean", "Double", "String", "Boolean", "Date"};
            private Class<?>[] types = {Integer.class, String.class, String.class, String.class, String.class,
                String.class, String.class, String.class, String.class};
            private int minimumDisplayedRow;
            public ConcreteTable() {
                this.minimumDisplayedRow = 10;
                this.datas = new ArrayList<ArrayList<Object>>();
                for (int i = 0; i < this.minimumDisplayedRow; i++) {
                    this.addEmptyRow();
                }
                Random rnd = new Random();
                for (int i = 0; i < 7; i++) {
                    ArrayList<Object> row = new ArrayList<Object>();
                    row.add(i);
                    row.add(((rnd.nextInt(25)) + "prova"));
                    row.add(rnd.nextInt(25));
                    row.add(rnd.nextInt(25) + 3.14);
                    row.add((i % 2 == 0) ? true : false);
                    row.add(rnd.nextInt(25) + 3.14);
                    row.add(((rnd.nextInt(25)) + "prova"));
                    row.add((i % 2 == 0) ? false : true);
                    cal = Calendar.getInstance();
                    cal.add(Calendar.DATE, -rnd.nextInt(25));
                    dateWithOutTime = cal.getTime();
                    String nullTimeForDateString = sdf.format(dateWithOutTime);
                    try {
                        dateWithOutTime = sdf.parse(nullTimeForDateString);
                    } catch (ParseException ex) {
                    }
                    row.add(dateWithOutTime);
                    this.addRow(row);
                }
            }
            @Override
            public String getColumnName(int col) {
                System.out.println("getColumnName " + col + " = " + columnNames[col]);
                return columnNames[col];
            }
            @Override
            protected Class<?>[] getTypeArray() {
                return this.types;
            }
            @Override
            protected ArrayList<Integer> getKeysColumnIndex() {
                ArrayList<Integer> keys = new ArrayList<Integer>();
                keys.add(0);
                return keys;
            }
            @Override
            public boolean isCellEditable(int row, int col) {
                System.out.println("isCellEditable row " + row + " col " + col);
                if (col == 1) {
                    System.out.println("TRUE");
                    return true;
                }
                return false;
            }
            @Override
            protected Object getGeneratedKeys(int col) {
                if (col != 0) {
                    return null;
                }
                return new Integer(this.rowNumber);
            }
            @Override
            protected int getMinimumDisplayedRow() {
                return this.minimumDisplayedRow;
            }
        }
        public abstract class AbstractTableMod extends AbstractTableModel {
            private static final long serialVersionUID = 1L;
            protected ArrayList<ArrayList<Object>> datas;
            protected int rowNumber = 0;
            protected abstract Class<?>[] getTypeArray();
            protected abstract ArrayList<Integer> getKeysColumnIndex();
            protected abstract Object getGeneratedKeys(int col);
            protected abstract int getMinimumDisplayedRow();
            public int getRowCount() {
                return this.datas.size();
            }
            @Override
            public int getColumnCount() {
                return this.getTypeArray().length;
            }
            @Override
            public Object getValueAt(int rowIndex, int columnIndex) {
                if (rowIndex >= this.rowNumber) {
                    return EMPTY_ROW;
                }
                try {
                    ArrayList<Object> row = this.datas.get(rowIndex);
                    if (row == null) {
                        return null;
                    }
                    Object obj = row.get(columnIndex);
                    return obj;
                } catch (IndexOutOfBoundsException e) {
                    return null;
                }
            }
            @Override
            public void setValueAt(Object value, int row, int col) {
                Class<? extends Object> targetColClass = this.getColumnClass(col);
                if (!targetColClass.isInstance(value)) {
                    return;
                }
                if (value instanceof String) {
                    String stringVal = (String) value;
                    if (stringVal.compareTo("") == 0) {
                        return;
                    }
                }
                if (row >= this.rowNumber) {
                    ArrayList<Object> newRow = new ArrayList<Object>();
                    ArrayList<Integer> keysIndexList = this.getKeysColumnIndex();
                    for (int i = 0; i < this.getColumnCount(); i++) {
                        if (i == col) {
                            newRow.add(value);
                        } else if (keysIndexList.contains(i)) {
                            newRow.add(this.getGeneratedKeys(i));
                        } else {
                            newRow.add(EMPTY_ROW);
                        }
                    }
                    this.addRow(newRow);
                } else {
                    this.datas.get(row).set(col, value);
                }
                this.fireTableCellUpdated(row, col);
            }
            @Override
            @SuppressWarnings("unchecked")
            public Class<? extends Object> getColumnClass(int c) {
                if (c > this.getTypeArray().length - 1) {
                    return null;
                } else {
                    return this.getTypeArray()[c];
                }
            }
            public void addEmptyRow() {
                ArrayList<Object> emptyRow = new ArrayList<Object>();
                for (int i = 0; i < this.getTypeArray().length; i++) {
                    emptyRow.add(EMPTY_ROW);
                }
                this.datas.add(emptyRow);
            }
            public void addRow(ArrayList<Object> row) {
                Object[] types = this.getTypeArray();
                if (types.length != row.size()) {
                    return;
                }
                for (int i = 0; i < row.size(); i++) {
                    Class<? extends Object> targetColClass = this.getColumnClass(i);
                    Object rowItem = row.get(i);
                }
                this.datas.add(this.rowNumber, row);
                this.rowNumber++;
                if (this.rowNumber < this.getMinimumDisplayedRow()) {
                    this.datas.remove(this.datas.size() - 1);
                }
                this.fireTableRowsInserted(this.rowNumber, this.rowNumber);
            }
        }
        public TableExample() {
            super("JTable example");
            getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
            ConcreteTable model = new ConcreteTable();
            tab = new JTable(model);
            TableRowSorter<ConcreteTable> sorter = new TableRowSorter<ConcreteTable>(model);
            try {
                sorter.setComparator(0, new EmptyRowComparator<Integer>(sorter, 0));
                sorter.setComparator(1, new EmptyRowComparator<String>(sorter, 1));
                sorter.setComparator(2, new EmptyRowComparator<String>(sorter, 2));
                sorter.setComparator(3, new EmptyRowComparator<String>(sorter, 3));
                sorter.setComparator(4, new EmptyRowComparator<String>(sorter, 4));
                sorter.setComparator(5, new EmptyRowComparator<String>(sorter, 5));
                sorter.setComparator(6, new EmptyRowComparator<String>(sorter, 6));
                sorter.setComparator(7, new EmptyRowComparator<String>(sorter, 7));
                sorter.setComparator(8, new EmptyRowComparator<String>(sorter, 8));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            tab.setRowSorter(sorter);
            JScrollPane table = new JScrollPane(tab);
            this.getContentPane().add(table);
            this.setSize(800, 400);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setRenderers();
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    setVisible(true);
                }
            });
            //TableExample tableExample = new TableExample();
        }
        public void setRenderers() {
            TableColumnModel m = tab.getColumnModel();
            //"Integer", "String", "Interger", "Double", "Boolean", "Double", "String", "Boolean", "Date"
            m.getColumn(0).setCellRenderer(NumberRenderer.getIntegerRenderer());
            m.getColumn(2).setCellRenderer(NumberRenderer.getIntegerRenderer());
            m.getColumn(3).setCellRenderer(NumberRenderer.getDoubleRenderer5());
            m.getColumn(5).setCellRenderer(NumberRenderer.getDoubleRenderer3());
            m.getColumn(8).setCellRenderer(FormatRenderer.getDateRenderer());
        }
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    TableExample tableExample = new TableExample();
                }
            });
            TableExample tableExample = new TableExample();
        }
    }
    class FormatRenderer extends DefaultTableCellRenderer {
        private static final long serialVersionUID = 1L;
        private Format formatter;
        private static DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");//standard continental EU date format
        FormatRenderer(Format formatter) {
            this.formatter = formatter;
        }
        @Override
        public void setValue(Object value) {
            try {
                if ((value != null)) {
                    if ((value instanceof Number) || (value instanceof Date)) {
                        setHorizontalAlignment(SwingConstants.RIGHT);
                        value = formatter.format(value);
                    }
                }
            } catch (IllegalArgumentException e) {
            }
            super.setValue(value);
        }
        public static FormatRenderer getDateRenderer() {
            return new FormatRenderer(dateFormat);
        }
    }
    class NumberRenderer extends FormatRenderer {
        private static final long serialVersionUID = 1L;
        private static Number numberValue;
        private static NumberFormat nf;
        NumberRenderer(NumberFormat formatter) {
            super(formatter);
            setHorizontalAlignment(SwingConstants.RIGHT);
        }
        public static NumberRenderer getIntegerRenderer() {
            return new NumberRenderer(NumberFormat.getIntegerInstance());
        }
        public static NumberRenderer getDoubleRenderer3() {
            nf = NumberFormat.getNumberInstance();
            nf.setMinimumFractionDigits(3);
            nf.setMaximumFractionDigits(3);
            nf.setRoundingMode(RoundingMode.HALF_UP);
            return new NumberRenderer(nf);
        }
        public static NumberRenderer getDoubleRenderer5() {
            nf = NumberFormat.getNumberInstance();
            nf.setMinimumFractionDigits(5);
            nf.setMaximumFractionDigits(5);
            nf.setRoundingMode(RoundingMode.HALF_UP);
            return new NumberRenderer(nf);
        }
    }
    
    

  • 답변 # 2

    정말 문제는 이전 토론과 관련이 없으며, 일반 바닐라가 있습니다 (내 영어 실력을 비교하십시오). 실제로 버그라고 생각합니까, 아니면 ViceVersaView를 보여 주면 누군가가 가능할 수 있습니다 영어로 된 JTable + TableModel + Comparator (JTable API의 TableRowSorter)에 대한 체인, eeeeeerghhh이 경우에는 정말 나쁜 것입니다.

    import java.awt.*;
    import java.awt.event.*;
    import java.util.Date;
    import javax.swing.*;
    import javax.swing.table.*;
    public class ViceVersaBugFromTableModelAndComparator {
        private String[] columnNames = {"String", "Integer", "Boolean", "Double", "Date"};
        private Object[][] data = {
            {"aaa", 12, true, .15, new Date()},
            {"bbb", 5, false, 100.01, new Date()},
            {"CCC", 92, true, 15.2, new Date()},
            {"DDD", 0, false, 10.80, new Date()},
            {"abc", 5, true, 4.11, new Date()},
            {"bae", 31, false, 100.01, new Date()},
            {"CAX", 27, true, 2.3, new Date()},
            {"AXD", 4, false, 50.00, new Date()},
            {"abc", 3, true, 1.5, new Date()},
            {"bae", 5, false, 1000, new Date()}, //java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.String
            //{"bae", 5, false, 1000.0, new Date()}, //un-comment for correctness
            {"CAX", 2, true, 21.7, new Date()},
            {"AXD", 2, false, 5.30, new Date()}
        };
        private TableModel model = new DefaultTableModel(data, columnNames) {
            private static final long serialVersionUID = 1L;
            @Override
            public Class<?> getColumnClass(int column) {
                return String.class;// again java.lang.ClassCastException 
                //return getValueAt(0, column).getClass(); //un-comment for correctness
            }
        };
        private JTable table = new JTable(model);
        private JTableHeader header;
        static class TestTableRowSorter extends TableRowSorter<TableModel> {
            public TestTableRowSorter(TableModel m) {
                super(m);
            }
            @Override
            public void toggleSortOrder(int column) {
            }
            public void wrapToggleSortOrder(int column) {
                super.toggleSortOrder(column);
            }
        }
        private Timer timer = new Timer(400, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("single");
                JTable table = header.getTable();
                RowSorter sorter;
                if (pt != null && table != null && (sorter = table.getRowSorter()) != null) {
                    int columnIndex = header.columnAtPoint(pt);
                    if (columnIndex != -1) {
                        columnIndex = table.convertColumnIndexToModel(columnIndex);
                        ((TestTableRowSorter) sorter).wrapToggleSortOrder(columnIndex);
                    }
                }
            }
        });
        private Point pt;
        public JComponent makeUI() {
            timer.setRepeats(false);
            table.setRowSorter(new TestTableRowSorter(model));
            header = table.getTableHeader();
            header.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(final MouseEvent e) {
                    if (timer.isRunning() && !e.isConsumed() && e.getClickCount() > 1) {
                        System.out.println("double");
                        pt = null;
                        timer.stop();
                    } else {
                        pt = e.getPoint();
                        timer.restart();
                    }
                }
            });
            JPanel p = new JPanel(new BorderLayout());
            p.add(new JScrollPane(table));
            return p;
        }
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    createAndShowGUI();
                }
            });
        }
        public static void createAndShowGUI() {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            f.getContentPane().add(new ViceVersaBugFromTableModelAndComparator().makeUI());
            f.setSize(820, 240);
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    }
    
    

  • 답변 # 3

    문제는 이중이 아니라 다른 것입니다. 스택 추적에서 볼 수 있듯이 테이블은 이중 값 ( javax.swing.JTable$DoubleRenderer )을 특별히 지원합니다. ).

    값이 setValue() 에 전달 된 문제   Double 가 아닙니다  그러나 다른 것입니다.

  • 답변 # 4

    문제는 : Double 값의 형식을 지정하면 문자열이되고, 열이 Double.class 만 허용하므로 되돌릴 수 없습니다. 따라서 Double.class를 String.class로 변경하면 작동합니다.

  • 이전 javascript - jquery - 아약스 응답에서 스크립트 평가
  • 다음 objective c - sqlite IPHONE에서 열과 같은 rowNum을 얻는 방법