如果我选择JTable
并在其模型上指定列的classtype,如下所示:
DefaultTableModel model = new DefaultTableModel(columnNames, 100) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}};
然后,当用户尝试在表格中输入double
值时,Swing会自动拒绝输入并将单元格的轮廓设置为红色。
当某人输入单元格的“负数或0”输入时,我希望发生相同的效果。我有这个:
@Override
public void setValueAt(Object val, int rowIndex, int columnIndex) {
if (val instanceof Number && ((Number) val).doubleValue() > 0) {
super.setValueAt(val, rowIndex, columnIndex);
}
}
}
这可以防止单元格接受任何非正值,但它不会将颜色设置为红色并使单元格保持可编辑状态。
我试着调查JTable默认情况下是如何做出拒绝的,但我似乎无法找到它。
如何拒绝非正输入以拒绝非整数输入?
由于
答案 0 :(得分:14)
private static class JTable.GenericEditor
使用内省来捕获通过构造具有无效Number
值的特定String
子类而引发的异常。如果您不需要此类通用行为,请考虑将PositiveIntegerCellEditor
创建为DefaultCellEditor
的子类。您的stopCellEditing()
方法会相应更简单。
附录:已更新以使用RIGHT
对齐和常见错误代码。
附录:另见Using an Editor to Validate User-Entered Text。
private static class PositiveIntegerCellEditor extends DefaultCellEditor {
private static final Border red = new LineBorder(Color.red);
private static final Border black = new LineBorder(Color.black);
private JTextField textField;
public PositiveIntegerCellEditor(JTextField textField) {
super(textField);
this.textField = textField;
this.textField.setHorizontalAlignment(JTextField.RIGHT);
}
@Override
public boolean stopCellEditing() {
try {
int v = Integer.valueOf(textField.getText());
if (v < 0) {
throw new NumberFormatException();
}
} catch (NumberFormatException e) {
textField.setBorder(red);
return false;
}
return super.stopCellEditing();
}
@Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
textField.setBorder(black);
return super.getTableCellEditorComponent(
table, value, isSelected, row, column);
}
}
答案 1 :(得分:2)
我明白了。如果给定的数字不是正数,则覆盖DefaultCellEditor并返回false
/将边框设置为红色。
不幸的是,由于JTable.GenericEditor是static
w / default
范围,我无法覆盖GenericEditor
来提供此功能,并且必须重新实现它w / a很少有调整,除非有人有更好的方法来做这件事,我想听听。
@SuppressWarnings("serial")
class PositiveNumericCellEditor extends DefaultCellEditor {
Class[] argTypes = new Class[]{String.class};
java.lang.reflect.Constructor constructor;
Object value;
public PositiveNumericCellEditor() {
super(new JTextField());
getComponent().setName("Table.editor");
((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT);
}
public boolean stopCellEditing() {
String s = (String)super.getCellEditorValue();
if ("".equals(s)) {
if (constructor.getDeclaringClass() == String.class) {
value = s;
}
super.stopCellEditing();
}
try {
value = constructor.newInstance(new Object[]{s});
if (value instanceof Number && ((Number) value).doubleValue() > 0)
{
return super.stopCellEditing();
} else {
throw new RuntimeException("Input must be a positive number.");
}
}
catch (Exception e) {
((JComponent)getComponent()).setBorder(new LineBorder(Color.red));
return false;
}
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected,
int row, int column) {
this.value = null;
((JComponent)getComponent()).setBorder(new LineBorder(Color.black));
try {
Class type = table.getColumnClass(column);
if (type == Object.class) {
type = String.class;
}
constructor = type.getConstructor(argTypes);
}
catch (Exception e) {
return null;
}
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
public Object getCellEditorValue() {
return value;
}
}
答案 2 :(得分:1)
此代码是对已接受答案的一个小改进。如果 用户不输入任何值,单击另一个单元格应该 允许他选择另一个单元格。接受的解决方案没有 允许这个。
@Override
public boolean stopCellEditing() {
String text = field.getText();
if ("".equals(text)) {
return super.stopCellEditing();
}
try {
int v = Integer.valueOf(text);
if (v < 0) {
throw new NumberFormatException();
}
} catch (NumberFormatException e) {
field.setBorder(redBorder);
return false;
}
return super.stopCellEditing();
}
此解决方案检查空文本。如果是空文本,我们调用stopCellEditing()
方法。
答案 3 :(得分:0)
因此,我首先创建了一个比喻,以使该主题更易于理解。
我们有一支笔(editor
。这支笔需要一些墨水(编辑者使用的墨水component
,组件的一个例子是JTextField
,JComboBox
等)来书写。
然后这是一支特殊的笔,当我们想用笔写东西时,我们会说(在GUI中键入行为)告诉它要写东西(写在model
中)。在将其写出之前,这支笔中的程序将评估该单词是否有效(通过stopCellEditing()
方法设置),然后将单词写在纸上(model
)。
自从我在DefaultCellEditor
部分花费了4个小时以来,想解释@trashgod的答案。
//first, we create a new class which inherit DefaultCellEditor
private static class PositiveIntegerCellEditor extends DefaultCellEditor {
//create 2 constant to be used when input is invalid and valid
private static final Border red = new LineBorder(Color.red);
private static final Border black = new LineBorder(Color.black);
private JTextField textField;
//construct a `PositiveIntegerCellEditor` object
//which use JTextField when this constructor is called
public PositiveIntegerCellEditor(JTextField textField) {
super(textField);
this.textField = textField;
this.textField.setHorizontalAlignment(JTextField.RIGHT);
}
//basically stopCellEditing() being called to stop the editing mode
//but here we override it so it will evaluate the input before
//stop the editing mode
@Override
public boolean stopCellEditing() {
try {
int v = Integer.valueOf(textField.getText());
if (v < 0) {
throw new NumberFormatException();
}
} catch (NumberFormatException e) {
textField.setBorder(red);
return false;
}
//if no exception thrown,call the normal stopCellEditing()
return super.stopCellEditing();
}
//we override the getTableCellEditorComponent method so that
//at the back end when getTableCellEditorComponent method is
//called to render the input,
//set the color of the border of the JTextField back to black
@Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
textField.setBorder(black);
return super.getTableCellEditorComponent(
table, value, isSelected, row, column);
}
}
最后,在您的类中使用此代码行初始化JTable来设置您的DefaultCellEditor
table.setDefaultEditor(Object.class,new PositiveIntegerCellEditor(new JTextField()));
Object.class
表示您希望应用编辑器的哪种列类
(您想使用那支笔的纸的哪一部分。它可以是Integer.class
,Double.class
和其他类)。
然后,我们在PositiveIntegerCellEditor()构造函数中传递new JTextField()
(确定要使用的墨水类型)。
如果我误解了任何事情,请告诉我。希望这会有所帮助!