I am struggling to see why this works. I have built a simple example using MVC to show a JTable that is editable and a button. The TableModel gets its data as an ArrayList supplied by the model. When a value is edited the table model updates the specific object in the ArrayList. When the user hits finish the actionlistener tells the controller finish has been hit, which calls a method in the model, finish(). All finish() does is iterate the ArrayList in a string output showing the values.
I just don't understand how AbstractTableModel updates the ArrayList in the model class. while it gets the ArrayList from the Model, it never calls a method to tell the model to update the ArrayList values. Any help would really be appreciated.
I have screenshots but I can't post them so here is the output with the default data
Int value: 1 String value: One
Int value: 2 String value: Two
And then when I change the int values to 11 and 22 in the JTable:
Int value: 11 String value: One
Int value: 22 String value: Two
Here is the full code:
public class Main {
public static void main(String args[]){
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Model model = new Model();
model.init();
new Controller(model);
}
});
}
}
import java.util.ArrayList;
public class Model {
private ArrayList<TableData> tableDataArrayList;
public Model(){
tableDataArrayList = new ArrayList<>();
}
public void init(){
tableDataArrayList.add(new TableData(1, "One"));
tableDataArrayList.add(new TableData(2, "Two"));
}
public ArrayList<TableData> getTableData(){
return tableDataArrayList;
}
public void finish(){
for(int x = 0; x < tableDataArrayList.size(); x++){
System.out.println("Int value: " + tableDataArrayList.get(x).getNumberValue() + " String value: " + tableDataArrayList.get(x).getStringValue());
}
}
}
public class Controller {
Model model;
MainGUI view;
public Controller(Model model){
this.model = model;
view = new MainGUI(this, this.model);
view.initGUI();
}
public void finish(){
model.finish();
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
public class MainGUI {
Controller controller;
Model model;
private JFrame mainFrame;
private JPanel mainContainer;
private JButton bFinish;
private JScrollPane jScrollPaneTable;
private JTable jTable;
TableModel tableModel;
ArrayList<TableData> tableDataArrayList;
public MainGUI(Controller controller, Model model){
this.controller = controller;
this.model = model;
tableDataArrayList = model.getTableData();
}
public void initGUI(){
mainFrame = new JFrame();
mainContainer = new JPanel();
tableModel = new TableModel(model);
jTable = new JTable(tableModel);
bFinish = new JButton("Finish");
bFinish.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
controller.finish();
}
});
jScrollPaneTable = new JScrollPane();
jScrollPaneTable.setMinimumSize(new Dimension(1800, 400));
jScrollPaneTable.getViewport().add(jTable);
mainContainer.add(jScrollPaneTable);
mainContainer.add(bFinish);
mainFrame.add(mainContainer);
mainFrame.setTitle("Tester");
mainFrame.setState(Frame.NORMAL);
//Exit window on close
mainFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
//Pack up JFrame
mainFrame.pack();
//Put Jframe in center
mainFrame.setLocationRelativeTo(null);
//This will set window to full stream
//mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
//Set frame visible
mainFrame.setVisible(true);
}
}
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
public class TableModel extends AbstractTableModel {
ArrayList<TableData> data;
String[] colNames = {"Int", "String"};
public TableModel(Model model){
this.data = model.getTableData();
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return colNames.length;
}
@Override
public String getColumnName(int column) {
return colNames[column];
}
@Override
public Object getValueAt(int rowIndex, int colIndex) {
TableData specData = data.get(rowIndex);
switch (colIndex){
case 0:
return specData.getNumberValue();
case 1:
return specData.getStringValue();
default:
return null;
}
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
TableData specData = data.get(rowIndex);
switch (columnIndex){
case 0:
specData.setNumberValue(Integer.parseInt(aValue.toString()));
break;
case 1:
specData.setStringValue(aValue.toString());
break;
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
}
public class TableData {
private int numberValue;
private String stringValue;
public TableData(int numberValue, String stringValue){
this.numberValue = numberValue;
this.stringValue = stringValue;
}
public void setNumberValue(int x){
numberValue = x;
}
public int getNumberValue(){
return numberValue;
}
public void setStringValue(String s){
stringValue = s;
}
public String getStringValue(){
return stringValue;
}
}