Search code examples
javaswingjtabletablemodel

java JTable replaced (?) but not being refreshed despite revalidate and repaint


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.


Solution

  • 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);