Подтверждено как ошибка на JTable не может отформатировать данный объект как Number, когда columnClass является Double (идентификатор ошибки: 7051636) . Не стесняйтесь голосовать за него, или, если у вас есть альтернативный (лучший) обходной путь, опубликуйте его в качестве комментария к отчету.
Я создаю JTable с пользовательской табличной моделью, построенной как расширение AbstractTableModel. Моя модель должна поддерживать пустую строку для отображения и сортировки. Поэтому я следил за этим сообщением , чтобы реализовать это, и теперь работает довольно хорошо.
У меня все еще есть проблема с форматированным полем в 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 вместо Integer:
public class MyModel extends AbstractTableModel{
public Object[] types= {new Double(0.0), ""};
.......
, я получу исключение Illegal Argument:
EDIT: новый вывод трассировки стека после предложения @Aaron Digulla
Исключение в потоке «AWT-EventQueue-0» java.lang.IllegalArgumentException: невозможно отформатировать данный объект как число в java.text.DecimalFormat.format (DecimalFormat.java:487) в java.text.Format.format (Format.java:140) в javax.swing.JTable $ DoubleRenderer.setValue (JTable.java:5352) в javax.swing.table.DefaultTableCellRenderer.getTableCellRendererComponent (DefaultTableCellRenderer.java:237) в javax.swing.JTable.prepareRenderer (JTable.java:5720) в javax.swing.plaf.basic.BasicTableUI.paintCell (BasicTableUI.java:2072) в javax.swing.plaf.basic.BasicTableUI.paintCells (BasicTableUI.java:1974) в javax.swing.plaf.basic.BasicTableUI.paint (BasicTableUI.java:1770) в javax.swing.plaf.ComponentUI.update (ComponentUI.java:143) в javax.swing.JComponent.paintComponent (JComponent.java:752) в javax.swing.JComponent.paint (JComponent.java:1029) в javax.swing.JComponent.paintChildren (JComponent.java:862) в javax.swing.JComponent.paint (JComponent.java:1038) в javax.swing.JViewport.paint (JViewport.java:747) в javax.swing.JComponent.paintChildren (JComponent.java:862) в javax.swing.JComponent.paint (JComponent.java:1038) в javax.swing.JComponent.paintChildren (JComponent.java:862) в javax.swing.JComponent.paint (JComponent.java:1038) в javax.swing.JComponent.paintChildren (JComponent.java:862) в javax.swing.JComponent.paint (JComponent.java:1038) в javax.swing.JLayeredPane.paint (JLayeredPane.java:567) в javax.swing.JComponent.paintChildren (JComponent.java:862) в javax.swing.JComponent.paintToOffscreen (JComponent.java:5131) в javax.swing.BufferStrategyPaintManager.paint (BufferStrategyPaintManager.java:278) в javax.swing.RepaintManager.paint (RepaintManager.java:1224) в javax.swing.JComponent.paint (JComponent.java:1015) в java.awt.GraphicsCallback $ PaintCallback.run (GraphicsCallback.java:21) в sun.awt.SunGraphicsCallback.runOneComponent (SunGraphicsCallback.java:60) в sun.awt.SunGraphicsCallback.runComponents (SunGraphicsCallback.java:97) в java.awt.Container.paint (Container.java:1780) в java.awt.Window.paint (Window.java:3375) в javax.swing.RepaintManager.paintDirtyRegions (RepaintManager.java:796) в javax.swing.RepaintManager.paintDirtyRegions (RepaintManager.java:713) в javax.swing.RepaintManager.seqPaintDirtyRegions (RepaintManager.java:693) в javax.swing.SystemEventQueueUtilities $ ComponentWorkRequest.run (SystemEventQueueUtilities.java:125) в java.awt.event.InvocationEvent.dispatch (InvocationEvent.java:209) в java.awt.EventQueue.dispatchEvent (EventQueue.java:597) в java.awt.EventDispatchThread.pumpOneEventForFilters (EventDispatchThread.java:269) в java.awt.EventDispatchThread.pumpEventsForFilter (EventDispatchThread.java:184) в java.awt.EventDispatchThread.pumpEventsForHierarchy (EventDispatchThread.java:174) в java.awt.EventDispatchThread.pumpEvents (EventDispatchThread.java:169) в 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
}
, все будет работать нормально, даже если какое-то поле таблицы является String. Мне это подсказывает, потому что Integer и Double можно преобразовать в String, это не вызовет проблем. В любом случае, я хотел бы понять, почему общий объект, такой как мой EMPTY_ROW, может быть принят как значение объявленного поля Integer, в то время как это не работает с полями Double.
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> implements Comparator
Если вы попытаетесь изменить
Class[] types = {Integer.class, String.class};
с помощью:
Class[] types = {Double.class, String.class};
, вы увидите проблему.