0

Having SSCCE as below, and assuming You are on GNU/Linux, please see if You can answer my question below. Save two files to "/tmp/aaa/some/packagepackagea/Test.java" and "/tmp/aaa/some/packagepackagea/DataHandler.java" or fix paths. I've tested that it compiles and runs.

Please fill table with your data, or press "save" (hardcoded paths ("/tmp/aaa/testdata"))

  1. I wonder why does not my JTable retrieve stored contents?
    Is it because final JTable table? If I understand it correctly, if table is final then d.load("/tmp/aaa/test", table, ";"); passes a copy (or a reference?) to DataHandler (d) load function. In this function i try to assign to final variable (?) or rather to reference that gets GC'ed after function exits anyway, so this is the reason my table has nothing after load?

Test.java

package some.packagepackagea;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import java.util.*;
import java.text.*;

public class Test {

    Test () {

        final DataHandler d = new DataHandler();

        JFrame root = new JFrame("zxczxc");
        root.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final javax.swing.table.DefaultTableModel model = new javax.swing.table.DefaultTableModel();
        final JPanel x = new JPanel();
        final JTable table = new JTable(model);
        JScrollPane table_container = new JScrollPane(table);

        // read some columns from file/db
        final String cols[] = {"aaaa", "bbbbb", "ccccc", "ddddd", "eeee"};
        for (String col:cols)
            model.addColumn(col);

        Object y[] = new Object[]{"a", "b"};
        model.addRow(y);
        model.addRow(y);
        JButton a = new JButton("save");
        JButton b = new JButton("load");

        x.add(a);
        x.add(b);
        x.add(table_container);

        a.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(ActionEvent e) {
                d.save(table, "/tmp/aaa/testdata", ";");
                x.revalidate();
                x.repaint();
            }
         });
        b.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(ActionEvent e) {
                d.load("/tmp/aaa/testdata", table, ";");
                model.fireTableDataChanged();
                x.revalidate();
                x.repaint();
            }
         });
        root.add(x);
        root.pack();                            // shrink borders
        root.setLocationRelativeTo(null);       // center panel
        root.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Test it = new Test();
            }
        });
    }
}

DataHandler.java

package some.packagepackagea;
import java.io.*;
import java.nio.CharBuffer;
import javax.swing.*;
import javax.swing.table.*;
import java.util.ArrayList;

public class DataHandler {

    public void save(JTable table, String file, String separator){
        File f = new File(file);
        save(table, f, separator);
    }

    public void save(JTable table, File file, String separator){

        try {
            TableModel tableModel = table.getModel();
            FileWriter disk = new FileWriter(file);

            for(int i = 0; i < tableModel.getColumnCount(); i++){
                disk.write(tableModel.getColumnName(i) + separator);
            }
            disk.write("\n");

            for(int i=0; i< tableModel.getRowCount(); i++) {
                for(int j=0; j < tableModel.getColumnCount(); j++) {
                    Object item = tableModel.getValueAt(i,j);
                    if (null != item)
                        disk.write(item.toString() + separator);
                }
                disk.write("\n");
            }
            disk.close();

            ((DefaultTableModel)tableModel).getDataVector().removeAllElements();

        } catch (IOException e){ System.out.println(e); }
    }

    public void load(String file, JTable table, String separator){
        File f = new File(file);
        load(f, table, separator);
    }

    public void load(File file, JTable table, String separator){

        CharBuffer buf = CharBuffer.allocate((int)file.length());
        try {
            FileReader disk = new FileReader(file);
            disk.read(buf);
            buf.rewind();
            disk.close();

        } catch (IOException e){ System.out.println(e); }

        String rows[] = (buf.toString()).split("\n");
        ArrayList<String[]> cols = new ArrayList<String[]>();
        for(String row:rows){
            cols.add(row.split(separator));
        }

        // it might be more efficient to return model and initialize table with
        // it but i find it nicer when methods are somewhat symmetric.
        TableModel tableModel = new DefaultTableModel();
        for(String[] col:cols){
            ((DefaultTableModel)tableModel).addRow(col);
        }
        table = new JTable(tableModel);
        ((DefaultTableModel)tableModel).fireTableDataChanged();
    }
}

EDIT:

I've tried also to replace

 table = new JTable(tableModel);

with

 table.setModel(tableModel);

but that didn't do the trick as well.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
kivy_student
  • 150
  • 1
  • 9

1 Answers1

2

You are creating a new table which isn't replacing referenced by the GUI.

So rewriting the load method a bit you could just set the model on the table, somthing like this:

String rows[] = (buf.toString()).split("\n");

DefaultTableModel tableModel = new DefaultTableModel();

for (String col:rows[0].split(separator))
    tableModel.addColumn(col);

for (int i = 1; i < rows.length; i++)
    tableModel.addRow(rows[i].split(separator));

table.setModel(tableModel);

The second thing is your save method. You are removing null values when outputting it to disk. Instead of:

Object item = tableModel.getValueAt(i,j);
if (null != item)
    disk.write(item.toString() + separator);

Do something like this:

Object item = tableModel.getValueAt(i,j);
disk.write((item != null ? item.toString() : "") + separator);
dacwe
  • 43,066
  • 12
  • 116
  • 140
  • Thanks, that actually works and I'm grateful (accepted), but could You please elaborate why my example didn't work? I understand that removing null items would break table layout, so empty strings are required (second part of Your answer) but no clue why load was wrong, i've even tried with `table.setModel(tableModel);` but it didn't work - no idea why. It started 'sort of' (sort of, probably because of missing null items it was mixed up) working when i constructed new `DefaultTableModel(2,2);` using different constructor. – kivy_student Nov 20 '15 at 13:40
  • The main problem (apart from constructing the model) was that you were resetting the `table` reference `table = new JTable();`. But that does not magically change the reference that the `frame` has. If you really want to change the whole `table` you need to replace the one the frame has. – dacwe Nov 20 '15 at 14:08
  • So, how is it actually, i thought that Java was always passing objects as references. So shouldn't it just create new object in same place (pointed by same name, table? Or update place table was pointing to, from addres, say 0x1234 to 0x2345?). Or is it like, `JScrollPane(table);` stores not a pointer but a "string pointer" and assigning to table creates new object somewhere else, but JScrollPane lookup address is not updated? And last thing - so JTable being final - had no inpact here? I mean, how was that even possible to make an assignment? – kivy_student Nov 20 '15 at 14:46
  • Java is [passed by value](http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value). – dacwe Nov 20 '15 at 15:04
  • Thanks...this does explain some nasty things for me. Much appreciated. – kivy_student Nov 20 '15 at 15:09