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