problem Formatierung der Felder in einer JTable - Unterschiede zwischen Integer und Double

Update

Bestätigt, als ein Fehler auf JTable kann nicht format-Objekts als Zahl, wenn columnClass ist Doppelt (bug ID: 7051636). Fühlen Sie sich frei, für ihn zu Stimmen, oder wenn Sie eine Alternative (besser) zu arbeiten, um, poste es als Kommentar zu dem Bericht.


Baue ich eine JTable mit einem eigenen Tisch-Modell gebaut erweitern AbstractTableModel.
Mein Modell unterstützen müssen leere Zeile angezeigt werden und sortiert werden.
Also ich follwed diese post zu implementieren, und jetzt funktioniert ziemlich gut.

Ich habe noch ein problem mit formatierten Bereich in eine JTable.
Angenommen, ich habe das folgende Modell:

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();

    }
}

Alles funktioniert einwandfrei.
Aber wenn ich eine Doppel-statt einer ganzen Zahl:

public class MyModel extends AbstractTableModel{

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

Werde ich ein Illegal Argument exception:

BEARBEITEN:
neue stack-trace-Ausgabe nach @Aaron Digulla Vorschlag

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

Warum?

getValueAt gibt immer den gleichen Wert zu füllen, alle Tabellen-Einträge mit es.
Dies ist nur für debug :

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

Zum Beispiel, wenn ich eine änderung an :

 @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
    }

alles Prima funktioniert, auch wenn einige Feld der Tabelle sind String. Er suggeriert mir, dass da
einen Integer-und einen Double umgewandelt werden kann, in String, dieser wird nicht zu Problemen führen.
Trotzdem würde ich gerne verstehen, warum ein generisches Objekt wie meine EMPTY_ROW akzeptiert werden können, da der Wert einer deklarierten Integer-Feld während dieser arbeiten nicht mit Doppel-Felder.

EDIT2:

Wenn ich entfernen getClass Methode in meiner Tabelle Modell. Es funktioniert. Trotzdem würde ich gerne lösen, ohne zu entfernen, die Methode, auch wenn dies zwingt mich zu implementieren, einige benutzerdefinierte render-Methoden.

EDIT3:

hier ist ein SSCCE. Es gibt einige Fehler beim hinzufügen neuer Werte in die Tabelle, aber noch nicht nichts zu tun mit der Darstellung Probleme.

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();
    }

}

Wenn Sie versuchen, sich zu ändern

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

mit :

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

können Sie sehen, die problem.

  • erste Double-Wert nicht 0.0
  • war eine Transkription Fehler. Weder mit 0,0 Werke
  • Für bessere Hilfe früher, nach einem SSCCE.
  • Thompson: ja, du hast Recht. Ich werde es in ein paar Minuten.
  • Thompson: ich habe bearbeitet meine Antwort. Finden Sie eine SSCCE zeigt das problem. vielen Dank für Ihre Aufmerksamkeit. Vielleicht findet man einige Fehler, aber ich hatte zu entfernen, die eine Menge von Zeilen aus meiner orignial-code um es kurz zu machen. Jede Hilfe wird sehr geschätzt.
  • Kopf) Ein SSCCE soll es sich um einen single-source-Datei, für die Bequemlichkeit der Helfer. Man könnte hinzufügen, die Klassen mit nicht main() in der Quelle mit main() wenn Sie reduzieren die Klasse Sichtbarkeit für 'Standard'. Und nur einen schwachen Punkt. Obwohl ich wäre daran interessiert, einen Blick auf die SSCCE, ich gebe keine Garantie, dass ich persönlich vorankommen können das problem. 😉
  • Thompson: tut mir Leid. Ich bin mit eclipse und ich copyed die drei Klassen, die ich brauchte. Ich Mach es jetzt. Kein problem, wenn Sie haben keine Garantien :), einen Versuch geben, wenn Sie etwas freie Zeit haben. Haben Sie schon, helfen Sie mir viel mit anderen Fragen..
  • Thompson: getan. Jetzt sollten Sie in der Lage sein zu kompilieren und auszuführen.
  • Habe ich einen Blick über ihn, aber habe einige Ideen. Bemerkt, dass wenn ich shove Doubles in der ersten Spalte aber behaupten, Sie sind Integers im getColumnClass() Daten geladen und sortiert, wie erwartet. Es scheint wie ein kompletter hack, aber gibt es einen speziellen Grund müssen Sie deklarieren Sie als Double eher als Integer? Ein weiterer Gedanke ist, dass dies scheint wie ein JRE-bug. Haben Sie hob einen Bericht? Wenn nicht, so tun Sie dies bitte.
  • Thompson. Ich wollte erklären, wie Sie doppelt, weil Sie doppelt sind. Blick auf die generierte Fehlermeldung zu deklarieren wie double, fühlte ich mich ein bisschen erschrocken, weil ich dachte, es wäre meine Schuld und das könnte Auswirkungen auf andere Teil meiner Umsetzung.Auch würde ich gerne umsetzen eine saubere Lösung, die in diesem Teil von meinem Projekt, weil diese Tabellen werden in einer Menge von anderen teilen des Antrags. Wie auch immer, ich werde es erklären, wie integer, bis ich erhalten eine Antwort. Ehrlich gesagt, ich habe nie hob einen bug-report (nie ein Fehler in einer Bibliothek, da jetzt). Ich werde sehen, was sind die Verfahren, und dann werde ich es tun. Dank
  • sind Sie wollen, um zu sehen, alle Daten der Klasse und nicht funktioniert??? mit deinem Beispiel .....
  • nicht jeder..ich will nur verstehen, warum, wenn ich die Lieferung an eine JTable-Objekt wie EMPTY_ROW es wird korrekt formatiert sein, ist das Feld ist vom Typ Integer, statt nicht zu arbeiten, wenn das Feld eingegeben wird, Verdoppeln. Der zusätzliche code, den Sie sehen, ist durch die Schaffung eines SSCCE aus einer mehr komplizierten Lösung. Eine Menge von Teil-code omissed.
  • ok vereinbart, ist der code nicht mir alle Sinne, cos arbeitet in der form, die Sie geschrieben, der Hinweis, was returs Objekt von JTable, vielen Dank für die Idee für mich gelöst
  • Thompson: endlich habe ich den Fehler gemeldet: bugs.sun.com/bugdatabase/view_bug.do?bug_id=7051636
  • Vielen Dank für die Berichterstattung, die. Ich bearbeitet die Frage hinzufügen, die info. wie ein update.
  • Thompson: danke für den edit. Bedeutet die Tatsache, dass der bug veröffentlicht wurde, bestätigen, dass es effectivly ein bug?
  • Thompson hmmm, sind Sie versucht, mein Beispiel, ich leaved Kommentar darüber, dass durch 0verbose Entscheidung, hier posten nur ausführbarer code für futures-Leser, dieses JTable-TableRowSorter-RowFilter-NestedComparator-AccesibleContext akzeptiert nur Integer und String, AFAIK gibt es (viele) Anzahl der Objektklassen, die sich weigerten, die von TableRowSorter&Komparator, da nur Integer, kann ich es nicht geschrieben hat Englisch korrekt, aber ziemlich sicher angenommen (Verschachtelte deklarierten Methoden für TableRowSorter&Komparator) Klasse String als default-Klasse zurückgegeben Objekt von JTable zu... 🙂
  • die Tatsache, dass der bug veröffentlicht wurde, bestätigen, dass es effektiv ein bug?" Ich denke, so. Ich musste einfach schauen, dass der Teil liest State 1-Dispatched, bug.
  • Sie versucht, mein Beispiel(?)" Nein (warten) ..ja. Es scheint zu Sortieren, die doppelten Werte nur in Ordnung. Vielleicht sollte eingegeben werden als 'work-around' an, dass der Fehler ( nach dem Tippfehler. befestigt ist ;)? Kann nicht sicher sagen, da ich noch nicht mehr getan, als kompilieren & führen Sie den code & sort einige Double Spalten.

InformationsquelleAutor Heisenbug | 2011-05-31
Schreibe einen Kommentar