JComboBox не всегда сохраняет значение в TableModel - PullRequest
0 голосов
/ 04 января 2019

Я создал JTable со списком лиц.Человек всегда может содержать другого человека (или, возможно, самого себя).Таким образом, пользователь может щелкнуть столбец, и появится JComboBox.Этот JComboBox содержит все лица JTable.

После того, как пользователь закончил редактирование JTable, он может нажать JButton «Сохранить».В этом примере он просто выведет значения TableModel на консоль.

Проблема: последнее изменение не «передано» TableModel.Например, пользователь выбирает для каждой строки человека Кима.Для него это выглядит правильно, но если вы нажмете кнопку, вы увидите, что в последнем ряду значение столбца «Персона» по-прежнему равно Джону.Когда пользователь нажимает на другой столбец, после изменения лиц в третьем столбце, а затем нажимает кнопку, вывод выводится правильно.

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

Для JTable я использовал этот урок: https://www.codejava.net/java-se/swing/how-to-create-jcombobox-cell-editor-for-jtable

Вот мой код:

public class Person {
    private String name;
    private Person person;
    private String job;

    public Person(String name, String job) {
        this.name = name;
        this.job = job;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

}

public class PersonTable extends JTable {

    private PersonTableModel tableModel;

    public PersonTable(List<Person> listPerson) {
        tableModel = new PersonTableModel(listPerson);
        this.setModel(tableModel);
        this.setDefaultRenderer(Person.class, new PersonCellRenderer());
        this.setDefaultEditor(Person.class, new PersonCellEditor(listPerson));
    }

    public Set<Person> getAllPersons() {
        Set<Person> set = new HashSet<Person>();
        for (int i = 0; i < tableModel.getRowCount(); i++) {
            set.add(tableModel.getPerson(i));
        }
        return set;
    }

}

public class PersonCellEditor extends AbstractCellEditor 
        implements TableCellEditor, ActionListener {

    private Person Person;
    private List<Person> listPerson;

    public PersonCellEditor(List<Person> listPerson) {
        this.listPerson = listPerson;
    }

    @Override
    public Object getCellEditorValue() {
        return this.Person;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {
        if (value instanceof Person) {
            this.Person = (Person) value;
        }

        JComboBox<Person> comboPerson = new JComboBox<Person>();
        comboPerson.setRenderer(new PersonComboBoxRenderer());

        for (Person aPerson : listPerson) {
            comboPerson.addItem(aPerson);
        }

        comboPerson.setSelectedItem(Person);
        comboPerson.addActionListener(this);

         if (isSelected) {
             comboPerson.setBackground(table.getSelectionBackground());
         } else {
             comboPerson.setBackground(table.getSelectionForeground());
         }

        return comboPerson;
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        JComboBox<Person> comboPerson = (JComboBox<Person>) event.getSource();
        this.Person = (Person) comboPerson.getSelectedItem();
    }

}

public class PersonCellRenderer extends DefaultTableCellRenderer {

     public Component getTableCellRendererComponent(JTable table, Object value, 
             boolean isSelected, boolean hasFocus, int row, int column) {
         if (value instanceof Person) {
             Person Person = (Person) value;
             setText(Person.getName());
         }

         if (isSelected) {
             setBackground(table.getSelectionBackground());
         } else {
             setBackground(table.getSelectionForeground());
         }

         return this;
     }

}

public class PersonTableModel extends AbstractTableModel {
    private String[] columnNames = {"No.", "Name", "Person", "Job"};
    private List<Person> listPerson = new ArrayList<>();

    public PersonTableModel(List<Person> listPerson) {
        this.listPerson.addAll(listPerson);
    }

    @Override
    public int getColumnCount() {
        return columnNames.length;
    }

    public String getColumnName(int column) {
        return columnNames[column];
    }

    public Class getColumnClass(int column) {
        return getValueAt(0, column).getClass();
    }

    @Override
    public int getRowCount() {
        return listPerson.size();
    }

    @Override
    public void setValueAt(Object value, int rowIndex, int columnIndex) {
        Person person = listPerson.get(rowIndex);

        switch (columnIndex) {
        case 1:
                person.setName((String) value);
            break;
        case 2:
                person.setPerson((Person) value);
            break;
        case 3:
                person.setJob((String) value);
            break;
        }        
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Object returnValue = null;
        Person person = listPerson.get(rowIndex);

        switch (columnIndex) {
        case 0:
                returnValue = rowIndex + 1;
            break;
        case 1:
                returnValue = person.getName();
            break;
        case 2:
                returnValue = person.getPerson();
            break;
        case 3:
                returnValue = person.getJob();
            break;
        }

        return returnValue;
    }

    public Person getPerson(int row) {
        return listPerson.get(row);
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex > 0;
    }    

}

public class PersonComboBoxRenderer extends DefaultListCellRenderer {

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
            boolean cellHasFocus) {
        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        if(value instanceof Person) {
            Person p = (Person) value;
            setText(p.getName());
        }
        return this;
    }

}

public class JComboBoxTableCellEditorExample extends JFrame {

    public JComboBoxTableCellEditorExample() {
        super("JComboBox Cell Editor for JTable Demo");

        List<Person> listPerson = new ArrayList<>();
        Person p1 = new Person("John", "Developer");
        Person p2 = new Person("Kim", "Designer");
        Person p3 = new Person("Peter", "Manager");
        p1.setPerson(p2);
        p2.setPerson(p3);
        p3.setPerson(p1);
        listPerson.add(p1);
        listPerson.add(p2);
        listPerson.add(p3);

        PersonTable table = new PersonTable(listPerson);

        JScrollPane scrollpane = new JScrollPane(table);
        scrollpane.setPreferredSize(new Dimension(400, 200));

        add(scrollpane, BorderLayout.CENTER);

        JButton buttonSave = new JButton("Save");
        buttonSave.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (Person p : table.getAllPersons()) {
                    System.out.println(p.getName() + " --> " + p.getPerson().getName());
                }
            }
        });

        add(buttonSave, BorderLayout.PAGE_END);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new JComboBoxTableCellEditorExample();
            }
        });
    }

}

1 Ответ

0 голосов
/ 04 января 2019

Я проверил ваш код и исправил проблему, применяя решение, описанное camickr здесь

Проблема, с которой вы сталкиваетесь, объясняется самим camickr в этой записи . Позвольте мне процитировать выдержку

При редактировании ячейки в JTable таблица не знает, когда пользователь закончил редактирование ячейки. Поэтому ответственность за скажите таблице, когда прекратить редактирование.

Обычно это делается:

  • с помощью клавиши ввода
  • вкладка в следующую ячейку
  • клик по другой ячейке с мышью

Если вы отредактируете Person третьего ряда [колонка 2] и сразу нажмете кнопку «Сохранить», JTable не обнаружит, что вы закончили редактирование этой ячейки. Вот почему вы получаете

Kim --> Kim
John --> Kim
Peter --> John

Одним из решений, предлагаемых camickr, является принудительное прекращение редактирования при обнаружении нажатия кнопки «Сохранить». Просто измените объявление кнопки

    JButton buttonSave = new JButton("Save");
    buttonSave.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (table.isEditing()) {
                table.getCellEditor().stopCellEditing();
            }

            for (Person p : table.getAllPersons()) {
                System.out.println(p.getName() + " --> " + p.getPerson().getName());
            }
        }
    });

Теперь вы должны получить желаемый результат.

Обратите внимание, что если вы немного измените свой класс PersonTable, заменив Set by List в методе getAllPersons, вы получите упорядоченный результат, улучшающий читабельность консоли.

public class PersonTable extends JTable {

    private PersonTableModel tableModel;

    public PersonTable(List<Person> listPerson) {
        tableModel = new PersonTableModel(listPerson);
        setModel(tableModel);
        setDefaultRenderer(Person.class, new PersonCellRenderer());
        setDefaultEditor(Person.class, new PersonCellEditor(listPerson));
    }

    public List<Person> getAllPersons() {
        List<Person> set = new ArrayList<Person>();

        for (int i = 0; i < tableModel.getRowCount(); i++) {
            set.add(tableModel.getPerson(i));
        }

        return set;
    }

}

Вывод на консоль без изменений с использованием списка

John --> Kim
Kim --> Peter
Peter --> John
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...