【问题标题】:Verifying JTable Input Gets Double Error Message验证 JTable 输入获取双重错误消息
【发布时间】:2018-07-01 07:51:33
【问题描述】:

我正在尝试编写一个 TableCellEditor 来验证 JTable 单元格的输入。我让它工作,除了错误消息显示两次。这是我的测试类:

import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

public class Tester {
    public static void main(String[] args) {
        JFrame frame=new JFrame();
        frame.setPreferredSize(new Dimension(500,100));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        DefaultTableModel model=new DefaultTableModel(null,new String[] {"Col 1","Col 2"});
        JTable table=new JTable(model);
        table.getColumnModel().getColumn(0).setCellEditor(new decimalCellEditor());
        model.insertRow(0,new Object[] {null,null});
        JScrollPane scroller=new JScrollPane(table);
        frame.add(scroller);
        frame.setVisible(true);
        frame.pack();
     }
}

这是编辑器:

 import java.awt.Component;

import javax.swing.AbstractCellEditor;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellEditor;


public class DecimalCellEditor extends AbstractCellEditor implements TableCellEditor {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private JTextField number=null;

    public DecimalCellEditor() {
        number=new JTextField();
    }

    @Override
    public Object getCellEditorValue() {
        String s=number.getText();
        if (s.equals("")) {
            return(s);
        }
        double x=0.;
        try {
            x=Double.parseDouble(s);
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(null,"Value must be numeric",null, JOptionPane.ERROR_MESSAGE, null);
            return("");
        }
        return(Double.toString(x));
    }

    @Override
    public Component getTableCellEditorComponent(JTable table_, Object value_, boolean isSelected_, int row_, int column_) {
        number.setText(String.valueOf(value_));
        return(number);
    }

    @Override
    public boolean stopCellEditing() {
        String s=(String) getCellEditorValue();
        if (s.equals("")) {
            return(super.stopCellEditing());
        }
        try {
            Double.parseDouble(s);
        } catch (NumberFormatException e) {
            fireEditingCanceled();
            return(false);
        }
        return(super.stopCellEditing());
    }
}

目标是确保用户输入数字值或根本不输入值 ("")。是什么导致错误在非数字时显示和消除两次,我该如何阻止它? TIA。

实施camickr的建议

假设我理解了建议,我不需要编辑器?

import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class Tester {
    public static void main(String[] args) {
        JFrame frame=new JFrame();
        frame.setPreferredSize(new Dimension(500,100));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        MyTableModel model=new MyTableModel(null,new String[] {"Col 1","Col 2"});
        JTable table=new JTable(model);
        model.insertRow(0,new Object[] {"",""});
        JScrollPane scroller=new JScrollPane(table);
        frame.add(scroller);
        frame.setVisible(true);
        frame.pack();
    }
}

覆盖 getColumnClass:

import javax.swing.table.DefaultTableModel;

public class MyTableModel extends DefaultTableModel {

/**
 * 
 */
private static final long serialVersionUID = 1L;

    public MyTableModel(Object[][] data_,String[] columnNames_) {
        super(data_,columnNames_);
    }

    @Override
    public Class<?> getColumnClass(int column_) {
        if (column_==0) {
            return(Double.class);
        }
        return(getValueAt(0,column_).getClass());
    }
}

我显然没有这样做,因为我从一个未知来源得到异常说:

线程“AWT-EventQueue-0”java.lang.IllegalArgumentException 中的异常:无法将给定对象格式化为数字

我猜我的构造函数有问题。

【问题讨论】:

  • 可能getCellEditorValue 被多次调用......就像在stopCellEditing() 和可能来自JTable。我会尽量不在stopCellEditing() 中使用它,直接从文本字段中获取文本(如getCellEditorValue() 中所做的那样)
  • 谢谢,但没用。它根本没有显示错误,这意味着 getCellEditorValue 未被调用。
  • The objective is to assure the user enters a numeric value or no value at all (""). - 只需覆盖 TableModel 的 getColumnClass(...) 方法以返回列的 Double.class,JTable 将使用适当的编辑器。单元格周围将放置一个红色边框,在解决问题之前您将无法保存数据。此外,类名应以大写字符开头。遵循 Java 约定!
  • 另外,为什么要将列的渲染器设置为新的 DefaultCellRenderer?教程曾经这样做过吗?无需实现整个编辑器界面。从 DefaultCellEditor 开始并自定义一些方法。查看:stackoverflow.com/questions/20390445/… 的自定义编辑器示例,当数据不正确时会显示错误消息。
  • 我认为我没有完全理解这个建议。我用我的新代码更新了 OP。

标签: java swing jtable tablecelleditor


【解决方案1】:

首先,类名应以大写字符开头。您已获得提供演示代码的 Swing 教程的链接。我确定您可以访问 Java API。 API 和示例都遵循相同的约定。通过示例学习并遵循 Java 约定!

目标是确保用户输入数字值或根本不输入值 ("")。

只需覆盖 TableModel 的 getColumnClass(...) 方法以返回列的 Double.class,JTable 将使用适当的编辑器和渲染器。

将在单元格周围放置一个红色边框,在您解决问题之前,您将无法保存数据。

无法将给定的对象格式化为数字

编辑:

花点时间想想你刚刚做出的改变。花点时间阅读错误消息。您的更改刚刚声明该列应包含Double 数据。那么为什么要在第一列中添加“空”字符串。渲染器如何将 String 转换为 Double?

同样,如果您阅读 Java 教程中的代码,您将了解如何将数字数据添加到 TableModel。很久以前我给了你一个该教程的链接,因为它包含许多基础知识。

【讨论】:

  • 我说数据应该包含数字或空字符串或没有条目或任何您想要调用的内容。这是问题的一部分。如何做到这一点,我认为你的建议考虑到了这一点。我不能通过 null 因为那也爆炸了。教程中甚至没有提到这一点,因此在这种情况下它们毫无用处。至于大写,那是一个错字,我只是没有在 OP 中更正它。我的 IDE 最初警告过我。
  • I said the data should contain numeric OR an empty string - 那么问题应该是我知道如何用数字初始化一行,但我不知道如何用空字符串来做。不要让我们猜测你真正的问题是什么。 I can't pass null - 适合我。但是再一次,您还没有发布MCVE 显示您尝试过的内容。 ` 我的 IDE 最初警告过我` - 再一次你不听给出的建议。似乎是您所有问题的共同主题。
  • Nothing in the tutorials even mentioned that so they are useless in this case - 不,他们展示了如何添加数字数据,这是第一步。然后你问一个后续问题。将您在测试期间发现的所有信息提供给我们,而不仅仅是一个“出了什么问题”的问题。努力!!!
  • 你越来越恼火了。更新后的 OP 是一个 MVCE。你甚至尝试过吗?正如我在 OP 中所说,目标是在该单元格中只允许数字或空字符串。我不知道你想从我这里得到什么。
  • 其实,你是那个令人沮丧的人,我是那个试图帮助的人。您显然不听我(或教程)所说的话,因为它总是需要第二次重复。我希望你注意,当人们试图帮助时???我给了你 MCVE 的功劳(关于它如何变得更好的建议)。然后你说当你通过 null 时会爆炸。好吧,你的 MCVE 在哪里验证或证明这个声明???因为是的,我测试了它,当您为数值指定 null 时,我知道它是如何工作的。
猜你喜欢
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2016-05-27
  • 2013-06-08
  • 1970-01-01
  • 2021-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多