带有“,”分隔符而不是“.”的 Jtable 数字编辑器
Jtable Number Editor with "," separator rather than "."
我是法国人,对 Java 并不陌生。
在法语中,双打有“,”分隔符而不是“.”。所以我有一个带有列 class = Double 的 JTable Cell,当我输入例如 2.4 时就可以了。但是当我输入 2,4 时它会阻塞。
我使用了 Locale.setDefault(Locale.FRENCH);
但结果相同:
正如您在下图中所见,我的应用程序以法语语言环境启动:
System Locale
有什么方法可以输入 2,4 而不是 2.4 吗?
此致
我建议您使用 AbstractTableModel
, then inside the method getValueAt(int row, int col)
use NumberFormat
实现自定义数据模型,如下所示:
NumberFormat.getInstance(Locale.FRENCH).format(2.4);
如果您的应用程序仅供法国用户使用,您可以将默认语言环境硬编码为法语。
Locale.setDefault( Locale.FRENCH );
Is there any way to enter 2,4 rather than 2.4 ?
好吧,有几个问题。
- 默认渲染器将显示“.”不是“,”。
- 默认编辑器将显示“.”,而不是“,”
- 当您尝试将值保存到 TableModel 时,默认编辑器无法将“,”识别为 Double 的有效字符
当您离开单元格时,输入的字符串必须转换为 Double
。但是,Double.parseDouble(...)
方法无法识别“,”,即使在使用法语语言环境时也是如此。
默认单元格编辑器意识到无法正确转换字符串,因此单元格以红色边框突出显示以指示无效值。
下面的解决方案使用自定义编辑器在内部处理“,”到“.”的转换。在 String 被解析为 Double 之前。它还将转换“。”为“,”,以便该值在编辑器中正确显示。
import java.awt.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class LocaleEditor extends DefaultCellEditor
{
private Object value;
public LocaleEditor()
{
super( new JTextField() );
((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT);
}
@Override
public Object getCellEditorValue()
{
return value;
}
@Override
public boolean stopCellEditing()
{
try
{
String editingValue = (String)super.getCellEditorValue();
// Don't allow user to enter "."
if (editingValue.contains("."))
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
return false;
}
// Replace local specific character
int offset = editingValue.lastIndexOf(",");
if (offset != -1)
{
StringBuilder sb = new StringBuilder(editingValue);
sb.setCharAt(offset, '.');
editingValue = sb.toString();
}
value = Double.parseDouble( editingValue );
}
catch(NumberFormatException exception)
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
return false;
}
return super.stopCellEditing();
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column);
JTextField textField = (JTextField)c;
textField.setBorder( new LineBorder(Color.BLACK) );
String text = textField.getText();
int offset = text.lastIndexOf(".");
// Display local specific character
if (offset != -1)
{
StringBuilder sb = new StringBuilder(text);
sb.setCharAt(offset, ',');
textField.setText( sb.toString() );
}
return c;
}
private static void createAndShowUI()
{
String[] columnNames = {"String", "Double", "Boolean"};
Object[][] data =
{
{"A", new Double(1), Boolean.TRUE },
{"B", new Double(2.25), Boolean.FALSE},
{"C", new Double(12.34), Boolean.TRUE },
{"D", new Double(1234.56), Boolean.FALSE}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers and editors to be used based on Class
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
return o.getClass();
}
return Object.class;
}
};
JTable table = new JTable(model);
table.setRowHeight(20);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
// Use a custom renderer and editor
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
nf.setMinimumFractionDigits(2);
TableCellRenderer renderer = new NumberRenderer( nf );
table.setDefaultRenderer(Double.class, renderer);
TableCellEditor fce = new LocaleEditor();
table.setDefaultEditor(Double.class, fce);
JFrame frame = new JFrame("Table Five Character Editor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( scrollPane );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
以上代码还使用了 Table Format Renderers 中的代码,它使您可以轻松地为给定的语言环境创建自定义渲染器。如果您不想使用渲染器,只需注释掉代码,然后注释掉“。”将显示在 table.
或者,作为解决方法,只需将所有列设置为 String
(因此,将接受所有输入),并在 DefaultTableModel
->TableModelListener
->tableChanged()
根据需要格式化字符串,然后使用 setValueAt()
.
将其解析为 Double
我是法国人,对 Java 并不陌生。 在法语中,双打有“,”分隔符而不是“.”。所以我有一个带有列 class = Double 的 JTable Cell,当我输入例如 2.4 时就可以了。但是当我输入 2,4 时它会阻塞。
我使用了 Locale.setDefault(Locale.FRENCH);
但结果相同:
正如您在下图中所见,我的应用程序以法语语言环境启动: System Locale 有什么方法可以输入 2,4 而不是 2.4 吗?
此致
我建议您使用 AbstractTableModel
, then inside the method getValueAt(int row, int col)
use NumberFormat
实现自定义数据模型,如下所示:
NumberFormat.getInstance(Locale.FRENCH).format(2.4);
如果您的应用程序仅供法国用户使用,您可以将默认语言环境硬编码为法语。
Locale.setDefault( Locale.FRENCH );
Is there any way to enter 2,4 rather than 2.4 ?
好吧,有几个问题。
- 默认渲染器将显示“.”不是“,”。
- 默认编辑器将显示“.”,而不是“,”
- 当您尝试将值保存到 TableModel 时,默认编辑器无法将“,”识别为 Double 的有效字符
当您离开单元格时,输入的字符串必须转换为 Double
。但是,Double.parseDouble(...)
方法无法识别“,”,即使在使用法语语言环境时也是如此。
默认单元格编辑器意识到无法正确转换字符串,因此单元格以红色边框突出显示以指示无效值。
下面的解决方案使用自定义编辑器在内部处理“,”到“.”的转换。在 String 被解析为 Double 之前。它还将转换“。”为“,”,以便该值在编辑器中正确显示。
import java.awt.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class LocaleEditor extends DefaultCellEditor
{
private Object value;
public LocaleEditor()
{
super( new JTextField() );
((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT);
}
@Override
public Object getCellEditorValue()
{
return value;
}
@Override
public boolean stopCellEditing()
{
try
{
String editingValue = (String)super.getCellEditorValue();
// Don't allow user to enter "."
if (editingValue.contains("."))
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
return false;
}
// Replace local specific character
int offset = editingValue.lastIndexOf(",");
if (offset != -1)
{
StringBuilder sb = new StringBuilder(editingValue);
sb.setCharAt(offset, '.');
editingValue = sb.toString();
}
value = Double.parseDouble( editingValue );
}
catch(NumberFormatException exception)
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
return false;
}
return super.stopCellEditing();
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column);
JTextField textField = (JTextField)c;
textField.setBorder( new LineBorder(Color.BLACK) );
String text = textField.getText();
int offset = text.lastIndexOf(".");
// Display local specific character
if (offset != -1)
{
StringBuilder sb = new StringBuilder(text);
sb.setCharAt(offset, ',');
textField.setText( sb.toString() );
}
return c;
}
private static void createAndShowUI()
{
String[] columnNames = {"String", "Double", "Boolean"};
Object[][] data =
{
{"A", new Double(1), Boolean.TRUE },
{"B", new Double(2.25), Boolean.FALSE},
{"C", new Double(12.34), Boolean.TRUE },
{"D", new Double(1234.56), Boolean.FALSE}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
// Returning the Class of each column will allow different
// renderers and editors to be used based on Class
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
return o.getClass();
}
return Object.class;
}
};
JTable table = new JTable(model);
table.setRowHeight(20);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
// Use a custom renderer and editor
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
nf.setMinimumFractionDigits(2);
TableCellRenderer renderer = new NumberRenderer( nf );
table.setDefaultRenderer(Double.class, renderer);
TableCellEditor fce = new LocaleEditor();
table.setDefaultEditor(Double.class, fce);
JFrame frame = new JFrame("Table Five Character Editor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( scrollPane );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
以上代码还使用了 Table Format Renderers 中的代码,它使您可以轻松地为给定的语言环境创建自定义渲染器。如果您不想使用渲染器,只需注释掉代码,然后注释掉“。”将显示在 table.
或者,作为解决方法,只需将所有列设置为 String
(因此,将接受所有输入),并在 DefaultTableModel
->TableModelListener
->tableChanged()
根据需要格式化字符串,然后使用 setValueAt()
.
Double