Как обновить jtable при использовании пользовательской TableModel со списком элементов, считанных из файла

у меня есть проблема с моей Jtable/TableModel, которую, сколько бы я ни пытался, я не могу исправить. Я работаю над программой адресной книги без программы базы данных, так как наш профессор хочет, чтобы мы учились всему вручную, поэтому у меня есть файл .csv, который я использую для чтения/записи контактов. я читаю контакты в файле, помещаю их в список, использую этот список для формирования TableModel вокруг него, а затем создаю Jtable с указанной TableModel. моя проблема возникает, когда, если я напишу новый контакт в файле, jtable не будет обновлять себя новой информацией, если я не закрою программу и не запущу ее снова. как я могу обновить таблицу с новой информацией?

здесь, где я впервые создаю модель jtable и table, я не буду публиковать весь метод, поскольку он не связан.

List<Contatcs> listContacts = createListContacts(username);
tableModel = new TableModel(listContacts);

//create table, sorter and set single selection model
jTable = new JTable(tableModel);
final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel);
JTableHeader jtHeader = jTable.getTableHeader();

здесь я создаю свой список контактов

public static List<Contatcs> createListContacts(String username) throws FileNotFoundException{

        String file = "CustomersAddressBooks\\" + username + ".csv";
        Scanner fileReader = new Scanner(new File(file));
        List<Contatcs> retVal = new ArrayList();
        while (fileReader.hasNextLine()){
            String line = fileReader.nextLine();
            line = line.replaceAll("\r||\n","");
            String[] var = line.split(",");
            if(!line.equals("") && !var[0].equals("FirstName") && !var[1].equals("LastName")){

                retVal.add(new Contatcs(var[0],var[1],var[2],var[3],var[4],var[5],var[6],var[7],var[8]));
            }
        }

        fileReader.close();

        return retVal;
    }

и это мой класс TableModel

public class TableModel extends AbstractTableModel {
    private static final int COLUMN_FIRSTNAME = 0;
    private static final int COLUMN_LASTNAME = 1;
    private static final int COLUMN_PHONENUMBER = 2;
    private static final int COLUMN_CITY = 3;

    private String[] columnNames = {"First Name", "Last Name", "Phone Number", "City"};
    private List<Contatcs> listContacts;

    public TableModel(List<Contatcs> listContacts){
        this.listContacts = listContacts;
        int indexCount = 1;
        for(Contatcs contact : listContacts){
            contact.setIndex(indexCount++);
        }
    }

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

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

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Contatcs contacts = listContacts.get(rowIndex);
        Object retVal = null;
        switch(columnIndex){
        case COLUMN_FIRSTNAME: retVal = contacts.getFirstName(); break;
        case COLUMN_LASTNAME: retVal = contacts.getLastName(); break;
        case COLUMN_PHONENUMBER: retVal = contacts.getPhoneNumber(); break;
        case COLUMN_CITY: retVal = contacts.getCity(); break;
        default: throw new IllegalArgumentException("Invalid column index.");
        }
        return retVal;
    }

    @Override
    public String getColumnName(int columnIndex){
        return columnNames[columnIndex];
    }
    @Override
    public Class<?> getColumnClass(int columnIndex){
        if(listContacts.isEmpty()) return Object.class;
        else return getValueAt(0,columnIndex).getClass();
    }
}

person cooldude22    schedule 23.07.2016    source источник
comment
1) Чтобы быстрее получить помощь, опубликуйте минимально воспроизводимый пример или Короткий, автономный, правильный пример. 2) Слова, набранные строчными буквами, плохо читаются, как будто пытаешься слушать, что кто-то бормочет. Пожалуйста, используйте заглавную букву в начале предложения, для слова I и имен собственных, таких как ArrayList или Oracle.   -  person Andrew Thompson    schedule 23.07.2016
comment
Не перерабатывайте имя интерфейса TableModel для подкласса.   -  person trashgod    schedule 23.07.2016


Ответы (1)


Это небольшой пример, кто это делает:

import java.util.Vector;

import javax.swing.table.AbstractTableModel;

public class TableModel extends AbstractTableModel {

    String[] column_name = new String[]{"Col1","Col2"};
    Vector<String[]> list_value=new Vector<String[]>();

    public TableModel() {
    }

    //add just one line the table
    public void add_row(String[] row_values){
        list_value.add(row_values);
    }

    //change the list 
    public void setList(Vector<String[]>list){
        this.list_value=list;
    }



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

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

    @Override
    public Object getValueAt(int row, int col) {
        return list_value.get(row)[col];
    }

}

а это кадр:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class MainFrame extends javax.swing.JFrame {
    private JButton button1;
    private JTextField val1;
    private JTextField val2;
    private JScrollPane scrollpanel;
    private JButton button_replace;
    private JTable table1;

    public static void main(String[] args) {
        MainFrame frame=new MainFrame();
        frame.show();
    }

    public MainFrame() {
        super();
        //creating components   
        FlowLayout thisLayout = new FlowLayout();
        getContentPane().setLayout(thisLayout);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        button1 = new JButton();
        getContentPane().add(button1);
        button1.setText("add");
        button1.setPreferredSize(new java.awt.Dimension(81, 23));
        val1 = new JTextField();
        getContentPane().add(val1);
        val1.setPreferredSize(new java.awt.Dimension(51, 23));
        val2 = new JTextField();
        getContentPane().add(val2);
        val2.setPreferredSize(new java.awt.Dimension(53, 23));
        pack();
        setSize(400, 300);
        //add the table now
        scrollpanel = new JScrollPane();        
        scrollpanel.setPreferredSize(new java.awt.Dimension(339, 169));
        getContentPane().add(scrollpanel);
        table1 = new JTable();
        scrollpanel.setViewportView(table1);
        table1.setModel(new jtableExemple.TableModel());
        TableModel table_model=(TableModel) table1.getModel();
        table_model.add_row(new String[]{"row1","row1"});
        table_model.add_row(new String[]{"row2","row2"});
        table_model.add_row(new String[]{"row3","row3"});
        button_replace = new JButton();
        getContentPane().add(button_replace);
        button_replace.setText("Replace all list");


        //add action to button 
        button1.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
            TableModel table_model=(TableModel) table1.getModel();
            table_model.add_row(new String[]{val1.getText(),val2.getText()});
            //this line to the change in the UI 
            table1.setRowHeight(table1.getRowHeight());
            }
        });

        button_replace.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                //create a random list
                TableModel table_model=(TableModel) table1.getModel();
                Vector<String[]>new_list=new Vector<String[]>();
                for(int i=0;i<100;i++)
                    new_list.add(new String[]{"new row "+i,"new row "+i});
                table_model.setList(new_list);
                //this line to the change in the UI 
                table1.setRowHeight(table1.getRowHeight());             
            }
        });

}


}
person Charif DZ    schedule 23.07.2016
comment
Конструктивная критика: если бы addRow() запустил подходящий TableModelEvent, удобно предоставленный AbstractTableModel, вам не понадобился бы ложный вызов для регулировки высоты строки. См. также Начальные потоки. - person trashgod; 23.07.2016
comment
DefaultTableModel — стандартный пример; подробнее здесь. - person trashgod; 23.07.2016
comment
Вы можете отредактировать мой ответ и показать мне, что делать, чтобы удалить setRowHeigh?! - person Charif DZ; 23.07.2016
comment
Я счастлив вести вас; попробуйте запустить событие в методе добавления строки и посмотрите, как это работает. - person trashgod; 24.07.2016
comment
большое спасибо: я добавил fireTableRowsInserted(list_value.size()-1, list_value.size()-1); и это сработало, теперь пришло время узнать об этом событии - person Charif DZ; 24.07.2016
comment
спасибо за помощь, ребята, моя проблема заключалась в том, что я не обновлял список массивов, на котором была основана модель таблицы, как только я это сделал, все сработало. у меня есть одна последняя проблема, которую я пытался исправить в течение 2 дней, в моем проекте у меня есть кнопка выхода из системы, которая очистит массив, чтобы он мог заполнить новые контакты для тех, кто снова войдет в систему, проблема я есть то, что даже если я повторно заполняю список новой информацией, модель таблицы, похоже, не замечает этого и все еще думает, что это пустой список, поэтому он ничего не отображает для тех, кто входит в систему, после того, как кто-то другой выходит из системы. - person cooldude22; 27.07.2016
comment
не берите в голову, ребята, у меня был момент прозрения, и я понял, что даже если я повторно заполнил список массивов, на самом деле он создавал новый объект, а модель таблицы застряла в предыдущем списке. спасибо за все ответы и помощь в любом случае. - person cooldude22; 27.07.2016