Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将JTable单元格输入标记为无效?_Java_Swing_Validation_Jtable_Tablecelleditor - Fatal编程技术网

Java 如何将JTable单元格输入标记为无效?

Java 如何将JTable单元格输入标记为无效?,java,swing,validation,jtable,tablecelleditor,Java,Swing,Validation,Jtable,Tablecelleditor,如果我使用JTable并在其模型上指定列的类类型,如下所示: DefaultTableModel model = new DefaultTableModel(columnNames, 100) { @Override public Class<?> getColumnClass(int columnIndex) { return Integer.class; }}; 这将防止单元格接受任何非正值,但不会将颜

如果我使用
JTable
并在其模型上指定列的类类型,如下所示:

   DefaultTableModel model = new DefaultTableModel(columnNames, 100) {
       @Override
        public Class<?> getColumnClass(int columnIndex) {
            return Integer.class;
        }};
这将防止单元格接受任何非正值,但不会将颜色设置为红色,并使单元格保持可编辑状态

我试着调查JTable在默认情况下是如何拒绝的,但我似乎找不到


我怎样才能让它拒绝非正输入,就像拒绝非整数输入一样?

我明白了。覆盖DefaultCellEditor并返回
false
/如果给定的数字不是正数,则将边框设置为红色

不幸的是,由于JTable.GenericEditor是
static
w/
default
scope,我无法覆盖
GenericEditor
来提供此功能,并且必须通过一些调整来重新实现它,除非有人有更好的方法来实现它,这是我想听到的

    @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;
        }
    }
通过使用无效的
String
值构造特定的
Number
子类,使用内省捕获引发的异常。如果您不需要这样的泛型行为,请考虑创建<代码> PosieTimeGeleCeleDels/Cuth>作为子类。您的
stopCellEditing()
方法将相应地更简单

附录:更新为使用对齐和常见错误代码

增编:另见

私有静态类PositiveIntegerCellEditor扩展了DefaultCellEditor{
专用静态最终边框红色=新线条边框(颜色为.red);
私有静态最终边框黑色=新线条边框(Color.black);
私有JTextField textField;
public PositiveIntegerCellEditor(JTextField textField){
超级(文本字段);
this.textField=textField;
this.textField.setHorizontalAlignment(JTextField.RIGHT);
}
@凌驾
公共布尔stopCellEditing(){
试一试{
int v=Integer.valueOf(textField.getText());
if(v<0){
抛出新的NumberFormatException();
}
}捕获(数字格式){
textField.setboorder(红色);
返回false;
}
返回super.stopCellEditing();
}
@凌驾
公共组件getTableCellEditorComponent(JTable表,
对象值,布尔值(选定,int行,int列){
textField.setboorder(黑色);
返回super.getTableCellEditorComponent(
表、值、isSelected、行、列);
}
}

此代码是对公认答案的一个小小改进。如果 用户未输入任何值,单击另一个单元格应 允许他选择另一个单元格。可接受的解决方案并不适用 允许这样做

@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(){
String text=field.getText();
如果(“.”等于(文本)){
返回super.stopCellEditing();
}
试一试{
int v=整数。value of(文本);
if(v<0){
抛出新的NumberFormatException();
}            
}捕获(数字格式){
字段.设置顺序(红色边框);
返回false;
}
返回super.stopCellEditing();
}

此解决方案检查是否存在空文本。对于空文本,我们调用
stopCellEditing()
方法

因此,首先我创建了一个类比,使这个主题更容易理解。
我们有一支笔(
编辑器
)。这支笔需要一些墨水(编辑器使用的
组件
,例如
JTextField
JComboBox
等等)来书写

然后这是一支特殊的笔当我们想用笔写东西时,我们说话(在GUI中输入行为)告诉它写东西(在
模型中写)。在写出之前,该笔中的程序将评估单词是否有效(在
stopCellEditing()
方法中设置),然后将单词写在纸上(
model

我想解释一下@trashgood的答案,因为我花了4个小时在
DefaultCellEditor
部分

//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);
    }
}  
Object.class
表示要应用编辑器的列类类型 (你想用那支笔的哪一部分。它可以是
Integer.class
Double.class
和其他类别)。
然后我们在PositiveIntegerCellEditor()构造函数中传递
新的JTextField()
(决定要使用哪种墨水)


如果我有什么误解,请告诉我。希望这有帮助

加1表示支持。您可以尝试将a传递给构造函数,但这并不是特别简单。谢谢,这更简洁。我确实返回并更新了我的代码,使其不那么通用,因为我只是想在一个我可以控制其使用的特定位置使用它。@trashgood+1嘿,trashgood使用文档过滤器来替代不允许用户类型是个好主意吗?@nachokk:是的,取决于上下文;否则,发出嘟嘟声的红色方框可能会有点烦人。:-)我也在想,如果您在
setValueAt(行、列)
中有自己的
AbstractTableModel
,您可以在那里验证它是否是一个业务逻辑,但随后您松开了发出嘟嘟声的红框:P
@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();
}
//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);
    }
}  
table.setDefaultEditor(Object.class,new PositiveIntegerCellEditor(new JTextField()));