加载JavaJTable:为什么它不工作?

加载JavaJTable:为什么它不工作?,java,swing,stream,load,jtable,Java,Swing,Stream,Load,Jtable,我创建了一个简单的GUI,其中包括一个JTable。此表可以通过适当的对象流保存和加载 此时,Save函数按预期工作,在Save目录中查看时,我可以看到table对象存储在一个文件中 但是,当我尝试从文件加载表时,GUI从不显示加载的表。actionlistener函数被调用,因为我有一个system.out“Data loaded”,但该表从不显示更新的数据 我已尝试调用repaint(),但无效。如果有人能让我知道我可能做错了什么,我将不胜感激 看一些代码 import javax.swin

我创建了一个简单的GUI,其中包括一个JTable。此表可以通过适当的对象流保存和加载

此时,Save函数按预期工作,在Save目录中查看时,我可以看到table对象存储在一个文件中

但是,当我尝试从文件加载表时,GUI从不显示加载的表。actionlistener函数被调用,因为我有一个system.out“Data loaded”,但该表从不显示更新的数据

我已尝试调用repaint(),但无效。如果有人能让我知道我可能做错了什么,我将不胜感激

看一些代码

import javax.swing.*;
import java.awt.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.imageio.*;
import java.io.*;
import java.awt.image.BufferedImage;
import java.util.*;
import javax.swing.table.*;
import java.awt.event.*;


public class Save3 extends JFrame implements ActionListener{

public int PADDING = 10;

public JMenuItem menuNew;
public JMenuItem menuOpen;
public JMenuItem menuSave;
public JMenuItem menuExit;

public JPanel       container;

public DefaultTableModel    model;
public JScrollPane          scrollPane;
public JTable               table;

public FileInputStream      fis;
public ObjectInputStream    in;
public FileOutputStream     fos;
public ObjectOutputStream   out;
public String               filename;


public Save3(){
    fis         = null;
    in          = null;
    fos         = null;
    out         = null;
    filename    = "test.ref";
    initGUI();
}

public void initGUI(){
    setTitle("WIM Reference Data Comparison Tool");
    setSize(500, 400);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);

    // Menu Bar and Menu Items setup
    JMenuBar    menuBar;
    JMenu       menu;
    JMenuItem   menuItem;

    menuBar = new JMenuBar();
    menu = new JMenu("Menu");
    menuBar.add(menu);

    menuNew     = new JMenuItem("New");
    menuOpen    = new JMenuItem("Open");
    menuSave    = new JMenuItem("Save");
    menuExit    = new JMenuItem("Exit");

    menuNew.addActionListener(this);
    menuOpen.addActionListener(this);
    menuSave.addActionListener(this);
    menuExit.addActionListener(this);

    menu.add(menuNew);
    menu.add(menuOpen);
    menu.add(menuSave);
    menu.add(menuExit);
    setJMenuBar(menuBar);               


    container       = new JPanel(new BorderLayout());

    String[] columnNames = {"", "MotorBike", " Car"}; 
    Object[][] data = { {"Vehicle Summary", new Integer(100), new Integer(200)},  // Header 1: Green
                        {"Axle Numbers", new Integer(100), new Integer(200)},
                        {"Axle Code", new Integer(100), new Integer(200)},
                        {"Axle Distances (cm)", new Integer(100), new Integer(200)},
                        {"Vehicle Speed (km/h)", new Integer(100), new Integer(200)},
                        {"Gross Weight", new Integer(100), new Integer(200)}, 
                        {"Axle Weight 1", new Integer(100), new Integer(200)},
                        {"Axle Weight 2", new Integer(100), new Integer(200)},
                        };

    model = new DefaultTableModel(data, columnNames);
    table = new JTable(data, columnNames);
    table.setPreferredScrollableViewportSize(new Dimension(500, 70)); 
    table.setFillsViewportHeight(true); 
    scrollPane = new JScrollPane(table); 


    container.add(scrollPane, BorderLayout.CENTER);
    add(container);
}



public void setPanel(JTable table){

    scrollPane.remove(table);
    container.remove(scrollPane);

    scrollPane  = new JScrollPane(table); 
    container.add(scrollPane, BorderLayout.CENTER);

    repaint();
}

public void actionPerformed(ActionEvent e){
    System.out.println("Clicked item!");
    // NEW
    if(e.getSource() == menuNew){
        System.out.println("New File");
    }
    // SAVE
    if(e.getSource() == menuSave){
        System.out.println("Save!");
        try{
            model.fireTableDataChanged();               
            table = new JTable(model);
            fos     = new FileOutputStream(filename);
            out     = new ObjectOutputStream(fos);
            out.writeObject(table);
        }catch(IOException e3){
            e3.printStackTrace();
        }
    }
    if(e.getSource() == menuOpen){
        System.out.println("Open!");

        JTable table = new JTable();
        try{
            fis     = new FileInputStream(filename);
            in      = new ObjectInputStream(fis);

            table   = new JTable();
            table   = (JTable) in.readObject();
            in.close(); 

            setPanel(table);

            System.out.println("data loaded");

        }catch(IOException e1){
            e1.printStackTrace();
        }catch(ClassNotFoundException e2){
            e2.printStackTrace();
        }
    }
    if(e.getSource() == menuExit){
        System.out.println("Exit!");
    }
}



   public static void main(String[] args) {

    SwingUtilities.invokeLater(new Runnable() {

        public void run() {

            try {
                UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
            } catch (Exception e) {
                e.printStackTrace();
            }

            Save3 ex = new Save3();
            ex.setVisible(true);
        }
    });
}

}

在执行的
操作代码中,导入的表(这是一个新实例)没有添加到容器中。

您的新表没有添加到任何位置,因此它不会显示。试着这样做:

public void actionPerformed(ActionEvent e){
  JTable oldTable = table;

  // your stuff, loading the table from file

  thePanelHoldingYourTable.remove(oldTable);
  thePanelHoldingYourTable.add(table);
  // if there are other components in that panel, make sure, your table is in the right spot
  // maybe refresh your layout by using invalidate()
}
编辑:好的,不建议序列化表,最好只保存表模型。这是您编辑的SSCCE(感谢kleopatra的帮助):

请注意,我使用以下三行序列化模型:

table.setModel(new DefaultTableModel());
out.writeObject(model);
table.setModel(model);
因此,在序列化时,模型与表分离。不幸的是,模型也尝试序列化其侦听器(失败)。这就是为什么这一步是必要的。保存后,模型可以再次应用于表。

  • 它是基于

  • 必须将数据从
    FileIO
    加载到结构中的
    XxxTableModel
    ,就像
    Vector
    Object[]

  • 对XxxTableModel的所有更新都必须在上完成,否则任何更改都会显示在屏幕上


我认为保存
JTable
不是一个好主意;保存
模型
更完美。即使对于模型,我也不会使用对象序列化(因为
Listener
s)。但是我不知道你的具体用例,这可能是合适的。SSCCE的概念是(如果你在Google上搜索或遵循@brimborium给出的链接,你就会知道)用最少的代码行(通常大约50行或更少)实现一个可运行的示例来演示问题。因此,请继续,扔掉与表格更新不直接相关的所有内容……你好,kleopatra,我现在已将代码更新为SSCCE标准。如果我没有弄错的话,第一点适用于
DefaultTableModel
<例如,code>AbstractTableModel
允许其他数据结构。谢谢,我不敢相信我忽略了这么小的东西。再补充一点,在添加新表后,我需要重新绘制()。很高兴我能帮上忙。尝试使用
invalidate()
而不是
repaint()
。我似乎太快了,无法将其标记为正确,即使在移除组件并将其添加到框架中时,表仍然没有重置@克利奥帕特拉,其实不是。我正在使用jdk1.6.0_30,如果我尝试
out.writeObject(model)
在上面的代码中(标准的
DefaultTableModel
model
),当在保存过程中选择表中的某个内容时,我得到一个
java.io.notserializableeexception:javax.swing.JTable$CellEditorRemover
。。。可能是模型试图序列化其侦听器(依我看,它不应该这样做,因为这样会间接序列化整个表)。可以通过在序列化模型之前从表中删除模型来检查该假设
table.setModel(new DefaultTableModel());
out.writeObject(model);
table.setModel(model);