jobr97
jobr97

Reputation: 179

How to save a class that extends AbstractTableModel into a file whenever it changes?

I have two classes. The first class mainWindow extends JFrame in there I have a JTable table1. In my second class I need to get this table. When I generate a getter in the mainWindow I need to do mainWindow win = new mainWindow(); in order to follow win.getTable1();. The problem is that the mainWindow win = new mainWindow(); thing openes the window, so that I got it twice in the end. How can I get a reference to my table1 form my second class?

mainWindow.java

package windows;

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import helpers.*;


public class mainWindow extends JFrame {

    private final String fileName = "Studenten";
    public studentTableModel model;
    private JPanel rootPanel;
    private JComboBox comboBox1;
    private JTable table1;
    private JButton generierenButton;
    private calculations calc = new calculations();

    public mainWindow() throws IOException {
        super("Zufallsgenerator fürs Repetieren");
        pack();

        setContentPane(rootPanel);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1000, 700);

        List<student> studentList = calc.readFromFile("Studenten");
        model = new studentTableModel(studentList);
        table1.setModel(model);
        setVisible(true);
    }
}

studentTableModel.java

package helpers;

import windows.mainWindow;

import javax.swing.table.AbstractTableModel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class studentTableModel extends AbstractTableModel {
    private calculations calc = new calculations();

    private final List<student> students;

    private final String[] columnNames = new String[] {
            "Id", "Name", "Bereits x-Mal repetiert", "Wahrscheinlichkeit", "im Pot"
    };

    private final Class[] columnClass = new Class[] {
            String.class, String.class, int.class, double.class, Boolean.class
    };

    public studentTableModel(List<student> students){
        this.students = students;
    }

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

    @Override
    public Class<?> getColumnClass(int columnIndex)
    {
        return columnClass[columnIndex];
    }

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

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

    @Override
    public Object getValueAt(int rowIndex, int columnIndex)
    {
        student row = students.get(rowIndex);
        if(0 == columnIndex) {
            return row.getId();
        }
        else if(1 == columnIndex) {
            return row.getName();
        }
        else if(2 == columnIndex) {
            return row.getAnzahlRepetitonen();
        }
        else if(3 == columnIndex) {
            return row.getWahrscheinlichkeit();
        }
        else if(4 == columnIndex) {
            return row.isInPot();
        }
        return null;
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex)
    {
        return true;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex)
    {
        student row = students.get(rowIndex);
        if(0 == columnIndex) {
            row.setId((String) aValue);
        }
        else if(1 == columnIndex) {
            row.setName((String) aValue);
        }
        else if(2 == columnIndex) {
            row.setAnzahlRepetitonen((Integer) aValue);
        }
        else if(3 == columnIndex) {
            row.setWahrscheinlichkeit((Double) aValue);
        }
        else if(4 == columnIndex) {
            row.setInPot((Boolean) aValue);
        }
        List<student> students1 = new ArrayList<student>();

        //here I need to get the table data to save it to a file using the method in the next class

        calc.saveToFile("newStudents", students1);

    }
}

calculations.java

package helpers;

import javax.swing.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class calculations {

    public void saveToFile(String file,List<student> studentList){
        int length = studentList.size();

        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(file);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        for (helpers.student student : studentList){
            String id = student.getId();
            String name = student.getName();
            int rep = student.getAnzahlRepetitonen();
            double wahrscheinlichkeit = student.getWahrscheinlichkeit();
            boolean inPot = student.isInPot();

            try {
                fileWriter.write(id + ";" + name + ";" + Integer.toString(rep) + ";" + Double.toString(wahrscheinlichkeit) + ";" + Boolean.toString(inPot) + "\n");
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
        }

        try {
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public List<student>readFromFile(String file){
        List<student> studentList = new ArrayList<student>();
        String line = null;
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }

        try {
            while ((line = br.readLine()) != null){
                student st = null;
                String[] cols = line.split(";");
                String id = cols[0];
                String name = cols[1];
                int rep = Integer.parseInt(cols[2]);
                double wahrscheinlichkeit = Double.parseDouble(cols[3]);
                boolean isPot = Boolean.parseBoolean(cols[4]);
                st = new student(id, name,rep, wahrscheinlichkeit, isPot);
                studentList.add(st);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        try {
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return studentList;
    }

    public List<student> getTableData(JTable table, List<student> studentList){
        int rows = table.getModel().getRowCount();
        for (int i = 0; rows >= i;){
            String id = (String) table.getModel().getValueAt(i, 0);
            String name = (String) table.getModel().getValueAt(i, 1);
            int anzahl = (int) table.getModel().getValueAt(i, 2);
            double prob = (Double) table.getModel().getValueAt(i, 3);
            boolean inPot = (Boolean) table.getModel().getValueAt(i, 4);
            studentList.add(new student(id, name, anzahl, prob, inPot));
            System.out.println("Read row " + i);
        }
        return studentList;
    }

}

changeListener

table1.getModel().addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                System.out.println("Change detected");
                List<student> newStudentList = new ArrayList<student>();
                calc.getTableData(table1, newStudentList);
                System.out.println("Now saving...");
                calc.saveToFile("newStudents", newStudentList);
            }
        });

Upvotes: 0

Views: 140

Answers (1)

null
null

Reputation: 5255

the program should have printed "Change detected" once there was a change in the table, but nothing happened.

it's true that addTableModelListener ...

[...] Adds a listener to the list that's notified each time a change to the data model occurs.

but by extending the abstract class AbstractTableModel it's your responsibility to cause such notification with the provided methods such as fireTableDataChanged() for example. When you do that is up to you, but the method setValueAt looks like a good place to notify the listeners, because it's the one that changes the table data.

Upvotes: 2

Related Questions