Lizzy Farrugia
Lizzy Farrugia

Reputation: 11

How to save an AbstractTableModel into a file?

I am trying to save edited rows from a JTable (type AbstractTableModel) into a file. I have no clue how to do this; either maybe with ObjectOutput and InputStream.

Furthermore, I would like to load it then, from another JTable when saved.

To give you a better picture, I am doing an EPOS system where a user can edit the row data (quantity), and when the program is executing, and finds that quantity is not zero it saves the entire row (with the current details) into a file. This is so that the user has a record that an order has been made (for the Sales functionality in an EPOS and Inventory).

The saving part will hopefully be triggered when the user clicks on the Confirm button.

Can someone please help me? Thanks

Upvotes: 0

Views: 462

Answers (1)

camickr
camickr

Reputation: 324197

If you read the JTable API you will find that it recommends that for long term storage you use the XMLEncoder.

I am trying to save edited rows from a JTable (type AbstractTableModel)

You are not using an AbstractTableModel. The AbstractTableModel does not provide any data storage. You are using a TableModel that extends AbstractTableModel. Assuming you are using the DefaultTableModel here is an example that allows you to use the XMLEncoder and XMLDecoder:

//  Following code is a more complete version of:
//  http://stackoverflow.com/q/26250939/131872

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.*;

public class DefaultTableModelPersistenceDelegateTest
{
    private File file = new File("TableModel.xml");
    private final JTextArea textArea = new JTextArea();

    private final String[] columnNames = {"Column1", "Column2"};

    private final Object[][] data =
    {
        {"aaa", new Integer(1)},
        {"bbb\u2600", new Integer(2)}
    };

    private DefaultTableModel model = new DefaultTableModel(data, columnNames);
    private final JTable table = new JTable(model);

    public JComponent makeUI()
    {
        model.setColumnCount(5);
        JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        sp.setResizeWeight(.3);
        sp.setTopComponent(new JScrollPane(table));
        sp.setBottomComponent(new JScrollPane(textArea));

        JPanel p = new JPanel();
        p.add(new JButton(new AbstractAction("XMLEncoder")
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try
                {
                    OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
                    XMLEncoder xe = new XMLEncoder(os);
                    xe.setPersistenceDelegate(DefaultTableModel.class, new DefaultTableModelPersistenceDelegate());
                    xe.writeObject(model);
                    xe.close();

                    Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
                    textArea.read(r, null);
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
        }));

        p.add(new JButton(new AbstractAction("XMLDecoder")
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try
                {
                    InputStream is = new BufferedInputStream( new FileInputStream( file ));
                    XMLDecoder xd = new XMLDecoder(is);
                    model = (DefaultTableModel)xd.readObject();
                    table.setModel(model);
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
        }));

        p.add(new JButton(new AbstractAction("clear")
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                model = new DefaultTableModel();
                table.setModel(model);
            }
        }));

        JPanel pnl = new JPanel(new BorderLayout());
        pnl.add(sp);
        pnl.add(p, BorderLayout.SOUTH);
        return pnl;
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            @Override public void run()
            {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new DefaultTableModelPersistenceDelegateTest().makeUI());
        f.setSize(420, 340);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

//  See following link for more information on Using XMLEncoder:
//  http://www.oracle.com/technetwork/java/persistence4-140124.html

class DefaultTableModelPersistenceDelegate extends DefaultPersistenceDelegate
{
    //  Initially creates an empty DefaultTableModel. The columns are created
    //  and finally each row of data is added to the model.

    @Override
    protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder encoder)
    {
        DefaultTableModel model= (DefaultTableModel)oldInstance;

        //  Create XML to restore the column names

        Vector<String> columnNames = new Vector<String>(model.getColumnCount());

        for (int i = 0; i < model.getColumnCount(); i++)
        {
            columnNames.add( model.getColumnName(i) );
        }

        Object[] columnNamesData = new Object[] { columnNames };
        encoder.writeStatement(new Statement(oldInstance, "setColumnIdentifiers", columnNamesData));

        //  Create XML to restore row data

        Vector row = model.getDataVector();

        for (int i = 0; i < model.getRowCount(); i++)
        {
            Object[] rowData = new Object[] { row.get(i) };
            encoder.writeStatement(new Statement(oldInstance, "addRow", rowData));
        }
    }
}

class DefaultTableModelPersistenceDelegate2 extends DefaultPersistenceDelegate
{
    //  Initially creates a DefaultTableModel with rows and columns. Then the
    //  columns are reset and proper names are used. Finally data is set for each
    //  cell in the model.

    @Override
    protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder encoder)
    {
        super.initialize(type, oldInstance, newInstance, encoder);

        DefaultTableModel model= (DefaultTableModel)oldInstance;

        //  Create XML to restore the column names

        Vector<String> columnNames = new Vector<String>(model.getColumnCount());

        for (int i = 0; i < model.getColumnCount(); i++)
        {
            columnNames.add( model.getColumnName(i) );
        }

        Object[] columnNamesData = new Object[] { columnNames };
        encoder.writeStatement(new Statement(oldInstance, "setColumnIdentifiers", columnNamesData));

        //  Create XML to reset the value of every cell to its value

        for (int row = 0; row < model.getRowCount(); row++)
        {
            for (int col = 0; col < model.getColumnCount(); col++)
            {
                Object[] o = new Object[] {model.getValueAt(row, col), row, col};
                encoder.writeStatement(new Statement(oldInstance, "setValueAt", o));
            }
        }
    }
}

If you are not using the DefaultTableModel then you will need to create your own PersistenceDelegate.

Upvotes: 1

Related Questions