При проверке ввода JTable появляется двойное сообщение об ошибке

Я пытаюсь написать 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: невозможно отформатировать данный объект как число

Я предполагаю, что проблема с моим конструктором.


person Wt Riker    schedule 22.01.2018    source источник
comment
вероятно, getCellEditorValue вызывается более одного раза ... как в stopCellEditing() и, возможно, из JTable. Я бы постарался не использовать его в stopCellEditing(), просто получить текст прямо из текстового поля (как это сделано в getCellEditorValue())   -  person user85421    schedule 22.01.2018
comment
Спасибо, но это не сработало. Ошибка вообще не отображалась, что означает, что getCellEditorValue не был вызван.   -  person Wt Riker    schedule 22.01.2018
comment
The objective is to assure the user enters a numeric value or no value at all (""). - просто переопределите метод getColumnClass(...) TableModel, чтобы вернуть Double.class для столбца, и JTable будет использовать соответствующий редактор. Вокруг ячейки появится красная рамка, и вы не сможете сохранить данные, пока не устраните проблему. Кроме того, имена классов должны начинаться с символа верхнего регистра. Соблюдайте соглашения Java!   -  person camickr    schedule 22.01.2018
comment
Кроме того, почему вы должны установить рендерер для столбца как новый DefaultCellRenderer? Учебники когда-либо делают это? Нет необходимости реализовывать весь интерфейс редактора. Начните с DefaultCellEditor и настройте некоторые методы. Проверьте: stackoverflow.com/questions/ 20390445 / - пример настраиваемого редактора, который отображает сообщение об ошибке, если данные неверны.   -  person camickr    schedule 22.01.2018
comment
Не думаю, что я полностью понял это предложение. Я обновил OP своим новым кодом.   -  person Wt Riker    schedule 22.01.2018
comment
Ну, по крайней мере, твои MCVE's поправляются. Знайте, можно ли включить код только в один класс, поэтому нам нужно скопировать / вставить только один исходный файл. Вы можете легко встроить настраиваемую TableModel в исходный код тестера с помощью статического класса. Смотрите редактирование моего ответа.   -  person camickr    schedule 22.01.2018
comment
Моя IDE не позволяет мне помещать 2 класса в один файл, поэтому их сложнее объединить. Я не могу вставить скопированный код в этот форум. Мне всегда приходится вручную редактировать его после вставки.   -  person Wt Riker    schedule 23.01.2018


Ответы (1)


Прежде всего, имена классов должны начинаться с символа верхнего регистра. Вам были предоставлены ссылки на учебные пособия по Swing, содержащие демонстрационный код. Я уверен, что у вас есть доступ к Java API. Все API и примеры следуют одному и тому же соглашению. Учитесь на примере и соблюдайте соглашения Java!

Цель состоит в том, чтобы убедиться, что пользователь вводит числовое значение или не вводит никакого значения («»).

Просто переопределите метод getColumnClass (...) TableModel, чтобы вернуть Double.class для столбца, и JTable будет использовать соответствующий редактор и средство визуализации.

Вокруг ячейки появится красная рамка, и вы не сможете сохранить данные, пока не устраните проблему.

Невозможно отформатировать данный объект как число

Редактировать:

Найдите время, чтобы подумать об изменении, которое вы только что сделали. Найдите время, чтобы прочитать сообщение об ошибке. В вашем изменении только что указано, что столбец должен содержать Double данные. Так почему вы добавляете «пустую» строку в первый столбец? Как средство визуализации может преобразовать String в Double?

Опять же, если вы прочитаете код в руководствах по Java, вы увидите, как числовые данные добавляются в TableModel. Я давным-давно дал вам ссылку на этот учебник, потому что он содержит много основ.

person camickr    schedule 22.01.2018
comment
Я сказал, что данные должны содержать числовое ИЛИ пустую строку, или без записи, или как вы хотите это называть. Это часть вопроса. Как это сделать, и я подумал, что ваше предложение учло это. Я не могу передать null, потому что он тоже взрывается. Ничего в обучающих материалах даже не упоминается, поэтому в данном случае они бесполезны. Что касается верхнего регистра, это была опечатка, которую я просто не исправил в OP. Моя IDE изначально предупреждала меня об этом. - person Wt Riker; 23.01.2018
comment
I said the data should contain numeric OR an empty string - тогда вопрос должен заключаться в том, что я знаю, как инициализировать строку с номером, но я не знаю, как это сделать с пустой строкой. Не заставляйте нас догадываться, в чем ваша настоящая проблема. I can't pass null - у меня отлично работает. Но еще раз вы не опубликовали MCVE, показывающее, что вы пробовали. «Моя IDE изначально предупреждала меня об этом» - и снова вы не слушаете данный совет. Кажется, это общая тема для всех ваших вопросов. - person camickr; 23.01.2018
comment
Nothing in the tutorials even mentioned that so they are useless in this case - нет, они показывают, как добавить числовые данные, что является первым шагом. Затем вы задаете дополнительный вопрос. Предоставьте нам всю информацию, которую вы обнаружили во время тестирования, а не только вопрос, в котором говорится, что не так. Сделать усилие!!! - person camickr; 23.01.2018
comment
Вы начинаете раздражать. Обновленный OP ЯВЛЯЕТСЯ MVCE. Вы хоть пробовали? Как я также сказал в OP, цель состоит в том, чтобы разрешить в этой ячейке только числовую или пустую строку. Я не знаю, чего ты от меня хочешь. - person Wt Riker; 23.01.2018
comment
На самом деле, ты разочаровывающий человек, я тот, кто пытается помочь. Вы тот, кто явно не слушает то, что я (или руководство) говорю, поскольку это всегда нужно повторять второй раз. Я ожидал, что вы обратите внимание, когда люди пытаются помочь ??? Я дал вам кредит за MCVE (с предложениями о том, как это может быть еще лучше). Затем вы сказали, что это взрывается, когда вы передаете null. Хорошо, где ваш MCVE, который подтверждает или демонстрирует это утверждение ??? Потому что да, я тестировал это, и именно поэтому я знаю, что он работает, когда вы указываете ноль для числового значения. - person camickr; 23.01.2018
comment
Хорошо, я согласен с этим, поскольку я не понял, о чем вы говорите. Я не обновлял {"",""} до {null,null} в OP, потому что не думал, что вы захотите скопировать все это снова. Я его обновил. Так что это работает для вас, а не для меня. Куда мы сейчас идем? Я использую Windows 7 Home Premium SP1 с JDK 8.0.730.2 и JRE 8.0.1610.12 с Eclipse Oxygen.A1 в качестве моей IDE. - person Wt Riker; 23.01.2018
comment
So it works for you and not for me. - 1) Мои комментарии касаются моего предложения, а не вашего оригинального подхода. Почему вы думаете, что я предлагаю альтернативный подход, а затем прокомментирую исходный код? 2) Сообщение об ошибке заключается в том, что вы не можете преобразовать объект в число. У вас есть только один столбец, который вы хотите использовать в качестве Double, так почему оба значения равны нулю? Опять же, мои комментарии напрямую касаются заявленной проблемы. В правильном MCVE у вас будет таблица с одним столбцом с Double, чтобы вы не отвлекались на другие данные. У вас проблемы с отладкой, потому что вы не можете упростить задачу. - person camickr; 23.01.2018
comment
Используя мое решение, у вас возникнет проблема с (null, null) из-за вашей реализации в методе getColumnClass (...). Вы не проверяете, содержат ли данные в строке null. - person camickr; 23.01.2018
comment
Мое обновление (реализация вашего предложения) - это то, о чем я думал, о чем мы говорим. Причина использования только первого столбца - упрощение кода. Я добавил второй столбец, чтобы он выглядел как настоящая таблица и относился к одному и тому же входу с умом. Это имеет значение? В любом случае, если я добавлю проверку на пустую запись, что должно вернуть getColumnClass, если предположить, что именно здесь возникает исключение? - person Wt Riker; 23.01.2018
comment
Неважно. Моя IDE выполнила обновление, которое не удалось. Где-то был сбой, поэтому мне нужно было переустановить некоторые библиотеки, чтобы с ним справиться. Я подозреваю, что что-то испортилось, но сейчас это работает. - person Wt Riker; 23.01.2018