JTable 中的格式化字段问题 - Integer 和 Double 之间的差异
##更新## 已确认为 JTable 上的错误,当 columnClass 为 Double 时,JTable 无法将给定对象格式化为数字(错误ID: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 异常:
编辑: @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.InitationEvent.dispatch(InitationEvent.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) 在 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 这样的通用对象可以被接受作为声明的 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<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};
用 :
Class[] types = {Double.class, String.class};
进行更改,你就会看到问题。
##Update##
Confirmed as a bug on JTable can't format given Object as Number when columnClass is Double (bug ID: 7051636). Feel free to vote for it, or if if you have an alternate (better) work-around, post it as a comment to the report.
I'm building a JTable with a custom table model built extending AbstractTableModel.
My model need to support empty row to be displayed and sorted.
So I follwed this post to implement that, and now works pretty fine.
I still have a problem whith formatted field in a JTable.
Suppose I have the following model:
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();
}
}
Everything works fine.
But if I have a Double instead of an Integer:
public class MyModel extends AbstractTableModel{
public Object[] types= {new Double(0.0), ""};
.......
I'll get an Illegal Argument exception:
EDIT:
new stack trace output after @Aaron Digulla suggestion
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)
Why this?
getValueAt returns always the same value to fill all tables entries with it.
This is only for debug :
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return this.EMPTY_ROW;
}
For example if i change to :
@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
}
all works fine even if some field of the table are String. It suggest to me that because
an Integer and a Double can be transformed into String, this won't cause problem.
Anyway I would like to understand why a generic Object like my EMPTY_ROW can be accepted as value of a declared Integer field while this don't work with Double fields.
EDIT2:
If I remove getClass method in my table model. It works. Anyway I would like to solve this without having to remove that method, even if this will force me to implement some custom render methods.
EDIT3:
here's an SSCCE. There is some errors while adding new values to the table, but hasn't nothing to do with rendering problems.
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();
}
}
If you try to change
Class[] types = {Integer.class, String.class};
with :
Class[] types = {Double.class, String.class};
you can see the problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Walter Laan
在他的帖子中怎么说编辑:我无法抗拒,但由于我的英语很差,我不敢评论为什么,在哪里以及如何可能,也不能正确工作,以确认我为 TableColumnRendering 添加了 Rob 的两个(一点点)修改类...,
how did
Walter Laan
says in his threadEDIT: I can't resist, but due to my poor English I dare not to commenting why, where and how is that possible, nor works correctly, for confirmations I added Rob's two (little bit) modified class for TableColumnRendering ...,
真正的问题是注意到与之前的辩论有关,有普通的香草(比较我缺少的英语技能),你认为这真的是错误吗,或者如果我展示了 ViceVersaView,也许有人可以评论 JTable + TableModel 的链+ 英语比较器(JTable API 的 TableRowSorter),eeeeeerghhh 在这种情况下真的是我的错
reall problem is noting to do with previous debate, there is plain vanilla (compare my missing English skills), are you think that that's really Bug, or if I showed ViceVersaView, maybe then somone can be able to comment that chains for JTable + TableModel + Comparator (TableRowSorter for JTable API) in English language, eeeeeerghhh really my bad in this case
问题不在于双重,而在于其他。正如您在堆栈跟踪中看到的,该表对双精度值有特殊支持 (
javax.swing.JTable$DoubleRenderer
)。问题是传递给
setValue()
的值不是Double
而是其他值。The problem is not the double but something else. As you can see in the stack trace, the table has special support for double values (
javax.swing.JTable$DoubleRenderer
).The problem us that the value passed to
setValue()
is not aDouble
but something else.问题是:当您格式化 Double 值时,它会变成字符串,您无法将其返回,因为该列只允许 Double.class。因此,如果将 Double.class 更改为 String.class,它将起作用。
The thing is: when you format the Double value, it becomes a string, you can't return it back cause the column only allows Double.class. So if you change the Double.class to String.class, it will work.