JTable Layout speichern und wieder laden

Florian Strienz

Erfahrenes Mitglied
Hallo zusammen,

gibt es einen eleganten Weg, dass Layout einer JTable beim schließen eines Programmes zu speichern und wenn das Programm mal wieder gestartet wird, dieses Layout wieder zu laden?

Mit Layout meine ich Spaltensortierung, Spaltenbreite, Position des Fensters in dem die JTable ist, Größe des Fensters,....

Folgendes habe ich versucht:

-das komplette Objekt auf die Platte schreiben (Serialisierung), hatte mehr oder weniger gut get, leider gab es immer wieder (sehr häufig) beim Laden exceptions, so dass das Layout wieder futsch war.

-die Werte manuell auslesen und in ein File schreiben und wieder neu setzten. Leider t das auch beim Laden nicht so richtig. Besonders die Sortierung der Spalten. Auch die Größe der Spalten wird nicht richtig gesetzt, wenn das Autoresize aktieviert ist (ist auch logisch, da bei jeder Änderung einer Spalte, die vorherige Spalte wieder automatisch angepackt wird.

Es muss doch noch eine dritte, elegante Möglichkeit geben. :) Hat jemand eine Idee/Wissen?

Gruß
Flo
 
Hallo,

schau mal hier:
Java:
/*
 * SaveAndRestoreJTableLayoutExample.java
 *
 * Created on 30. April 2008, 20:39
 */
package de.tutorials.training;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 *
 * @author  Tom
 */
public class SaveAndRestoreJTableLayoutExample extends javax.swing.JFrame {

    public final static String LAYOUT_DESCRIPTOR = "table-layout.xml";

    /** Creates new form SaveAndRestoreJTableLayoutExample */
    public SaveAndRestoreJTableLayoutExample() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        scrollPane = new javax.swing.JScrollPane();
        table = new javax.swing.JTable();
        btnSaveLayout = new javax.swing.JButton();
        btnRestoreLayout = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("SaveAndrestoreJTableLayoutExample");

        table.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {new Boolean(true), "a", "1", "A"},
                {null, "b", "2", "B"},
                {new Boolean(true), "c", "3", "C"},
                {null, "d", "4", "D"}
            },
            new String [] {
                "Column0", "Column1", "Column2", "Column3"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.Boolean.class, java.lang.String.class, java.lang.Object.class, java.lang.String.class
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
        });
        scrollPane.setViewportView(table);

        btnSaveLayout.setText("Save Layout");
        btnSaveLayout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSaveLayoutActionPerformed(evt);
            }
        });

        btnRestoreLayout.setText("RestoreLayout");
        btnRestoreLayout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRestoreLayoutActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(btnSaveLayout)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btnRestoreLayout)
                .addContainerGap(183, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 239, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnSaveLayout)
                    .addComponent(btnRestoreLayout))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>
    private void btnSaveLayoutActionPerformed(java.awt.event.ActionEvent evt) {
        TableColumnModel tableColumnModel = this.table.getColumnModel();
        final Set<TableColumnLayoutInfo> tableColumnLayoutInfos = new TreeSet<TableColumnLayoutInfo>();

        for (int currentColumnIndex = 0; currentColumnIndex < tableColumnModel.getColumnCount(); currentColumnIndex++) {
            TableColumn tableColumn = tableColumnModel.getColumn(currentColumnIndex);
            TableColumnLayoutInfo tableColumnLayoutInfo = new TableColumnLayoutInfo(tableColumn.getIdentifier().toString(),
                    tableColumnModel.getColumnIndex(tableColumn.getIdentifier()), tableColumn.getWidth());
            tableColumnLayoutInfos.add(tableColumnLayoutInfo);
        }

        try {
            XMLEncoder xmlEncoder = new XMLEncoder(new FileOutputStream(LAYOUT_DESCRIPTOR));
            xmlEncoder.writeObject(tableColumnLayoutInfos);
            xmlEncoder.close();
        } catch (IOException exception) {
            exception.printStackTrace();
        }  
    }

    private void btnRestoreLayoutActionPerformed(java.awt.event.ActionEvent evt) {
        try {
            XMLDecoder xmlDecoder = new XMLDecoder(new FileInputStream(LAYOUT_DESCRIPTOR));
            Set<TableColumnLayoutInfo> tableColumnLayoutInfos = (Set<TableColumnLayoutInfo>) xmlDecoder.readObject();
            xmlDecoder.close();

            TableColumnModel tableColumnModel = new DefaultTableColumnModel();

            for (TableColumnLayoutInfo tableColumnLayoutInfo : tableColumnLayoutInfos) {
                TableColumn tableColumn = table.getColumn(tableColumnLayoutInfo.getColumnName());
                tableColumn.setPreferredWidth(tableColumnLayoutInfo.getWidth());
                tableColumnModel.addColumn(tableColumn);
            }

            this.table.setColumnModel(tableColumnModel);

        } catch (Exception exception) {
            exception.printStackTrace();
        }

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new SaveAndRestoreJTableLayoutExample().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JButton btnRestoreLayout;
    private javax.swing.JButton btnSaveLayout;
    private javax.swing.JScrollPane scrollPane;
    private javax.swing.JTable table;
    // End of variables declaration
    public static class TableColumnLayoutInfo
            implements Serializable, Comparable<TableColumnLayoutInfo> {

        public int compareTo(TableColumnLayoutInfo o) {
            return order - o.order;
        }
        private int order;
        private String columnName;
        private int width;

        public TableColumnLayoutInfo() {
        }

        public TableColumnLayoutInfo(String columnName, int order, int width) {
            this.columnName = columnName;
            this.order = order;
            this.width = width;
        }

        public int getOrder() {
            return order;
        }

        public void setOrder(int order) {
            this.order = order;
        }

        public int getWidth() {
            return width;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        public String getColumnName() {
            return columnName;
        }

        public void setColumnName(String columnName) {
            this.columnName = columnName;
        }
    }
}

Gruß Tom
 
Endlich bin ich mal dazu gekommen, deinen Code auszuporbieren.

Super cool! Danke Tom.

Ich habe deinen Code benutzt und mir eine eigene JFrame Klasse geschrieben die auch gleich die Fensterposition und Größe mitspeichert. Tabellen können beliebig viele hinzugefügt und mit abgespeichert werden.

Gespeichert wird das ganze im Awendungsdatenverzeichnis (System.getProperty("java.io.tmpdir"). Der Filename leitet sich aus dem Klassennamen und Package ab.

Hier der Code falls das noch jemand mal benötigt.

Gruß
Flo

Code:
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Set;
import java.util.TreeSet;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

public class MyJFrame extends JFrame {

	private File SETTINGS_FILE = new File(System.getProperty("java.io.tmpdir")
			+ "/MeinProgramm/" + getClass().getName());

	private ArrayList<JTable> tables = new ArrayList<JTable>();

	public MyJFrame() throws HeadlessException {
		initilaize();
	}

	public MyJFrame(GraphicsConfiguration gc) {
		super(gc);
		initilaize();
	}

	public MyJFrame(String title) throws HeadlessException {
		super(title);
		initilaize();
	}

	public MyJFrame(String title, GraphicsConfiguration gc) {
		super(title, gc);
		initilaize();
	}

	private void initilaize() {
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				saveWindowState();
			}
		});

	}

	public void addJTable(JTable table) {
		tables.add(table);
	}

	public void reloadWindowState() {
		try {
			if (SETTINGS_FILE.exists()) {
				XMLDecoder decoder = new XMLDecoder(new FileInputStream(
						SETTINGS_FILE));

				// Fensterposition
				Dimension d = (Dimension) decoder.readObject();
				Point p = (Point) decoder.readObject();

				setSize(d);
				setLocation(p);

				// Tabelle
				for (JTable table : tables) {
					@SuppressWarnings("unchecked")
					Set<TableColumnLayoutInfo> tableColumnLayoutInfos = (Set<TableColumnLayoutInfo>) decoder
							.readObject();

					TableColumnModel tableColumnModel = new DefaultTableColumnModel();

					for (TableColumnLayoutInfo tableColumnLayoutInfo : tableColumnLayoutInfos) {

						TableColumn tableColumn = table
								.getColumn(tableColumnLayoutInfo
										.getColumnName());

						tableColumn.setPreferredWidth(tableColumnLayoutInfo
								.getWidth());

						tableColumnModel.addColumn(tableColumn);

					}

					TableColumnModel model = table.getColumnModel();
					for (int i = 0; i < model.getColumnCount(); i++) {
						boolean found = false;
						for (int z = 0; z < tableColumnModel.getColumnCount(); z++) {
							if (tableColumnModel
									.getColumn(z)
									.getHeaderValue()
									.equals(model.getColumn(i).getHeaderValue())) {
								found = true;
								break;
							}
						}
						if (!found) {
							tableColumnModel.addColumn(model.getColumn(i));
						}
					}

					table.setColumnModel(tableColumnModel);
				}

				decoder.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void saveWindowState() {
		try {

			SETTINGS_FILE.getParentFile().mkdirs();
			XMLEncoder encoder = new XMLEncoder(new FileOutputStream(
					SETTINGS_FILE));

			// Fensterposition
			encoder.writeObject(this.getSize());
			encoder.writeObject(this.getLocation());

			// Tabelleninfo
			for (JTable table : tables) {
				TableColumnModel tableColumnModel = table.getColumnModel();

				final Set<TableColumnLayoutInfo> tableColumnLayoutInfos = new TreeSet<TableColumnLayoutInfo>();

				for (int currentColumnIndex = 0; currentColumnIndex < tableColumnModel
						.getColumnCount(); currentColumnIndex++) {

					TableColumn tableColumn = tableColumnModel
							.getColumn(currentColumnIndex);

					TableColumnLayoutInfo tableColumnLayoutInfo = new TableColumnLayoutInfo(
							tableColumn.getIdentifier().toString(),

							tableColumnModel.getColumnIndex(tableColumn
									.getIdentifier()), tableColumn.getWidth());

					tableColumnLayoutInfos.add(tableColumnLayoutInfo);

				}
				encoder.writeObject(tableColumnLayoutInfos);
			}

			encoder.flush();
			encoder.close();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			setVisible(false);
			dispose();
		}
	}

	public static class TableColumnLayoutInfo

	implements Serializable, Comparable<TableColumnLayoutInfo> {

		public int compareTo(TableColumnLayoutInfo o) {

			return order - o.order;

		}

		private int order;

		private String columnName;

		private int width;

		public TableColumnLayoutInfo() {

		}

		public TableColumnLayoutInfo(String columnName, int order, int width) {

			this.columnName = columnName;

			this.order = order;

			this.width = width;

		}

		public int getOrder() {

			return order;

		}

		public void setOrder(int order) {

			this.order = order;

		}

		public int getWidth() {

			return width;

		}

		public void setWidth(int width) {

			this.width = width;

		}

		public String getColumnName() {

			return columnName;

		}

		public void setColumnName(String columnName) {

			this.columnName = columnName;

		}

	}

}
 
Zurück