JTable save on exit. And load on start-up

I've looked at many many examples of saving JTable but i'm not getting closer to finishing my project.

I am using DefaultTableModel and JTable. When i open the program everything works and i can add a row, remove a row and such, but I need to save the values inside the JTable at close and open them again when i open the program again.

I've not specified any ArrayList or Vector but it is my understanding that DefaultTableModel saves the inserted rows in Vector.  I will attach all my code so you can maybe find out what is wrong.... I tried inserting fireTableDataChanged, and setValueAt, but maybe i waas doing it wrong

Thank You
kv Jón Orri Sigurðarson


import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.text.*;

public class jozioforrit extends JPanel {
	
	class AboutDialog extends JDialog {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public AboutDialog(JFrame parent) {
			setMaximumSize(new Dimension(250,150));
			Box b = Box.createVerticalBox();
			try {
				Object columnrow = table.getModel().getValueAt(table.getSelectedRow(),0);
				String banan = columnrow.toString();
				String banani = banan.replace(' ', '+');
				URL url = new URL("http://en.wikiwix.com/export/export.php?backend=html&url=http://en.wikipedia.org/wiki/" + banani);
				String banana = url.toString();
				System.out.println(banana);
				JEditorPane pppane = new JEditorPane();
				pppane.setPage(url);
				JScrollPane skroll = new JScrollPane(pppane);
				b.add(skroll);
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			getContentPane().add(b, "Center");
			setSize(750, 500);
			setLocation(400,70);
		}
	}

	public class ButtonColumn extends AbstractCellEditor implements
			TableCellRenderer, TableCellEditor, ActionListener, MouseListener {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private Action action;
		private JButton editButton;
		private Border focusBorder;
		private boolean isButtonColumnEditor;
		private int mnemonic;

		private Border originalBorder;
		private JButton renderButton;
		private JTable table;
		private String text;

		/**
		 * Create the ButtonColumn to be used as a renderer and editor. The
		 * renderer and editor will automatically be installed on the
		 * TableColumn of the specified column.
		 * 
		 * @param table
		 *            the table containing the button renderer/editor
		 * @param action
		 *            the Action to be invoked when the button is invoked
		 * @param column
		 *            the column to which the button renderer/editor is added
		 */
		public ButtonColumn(JTable table, Action action, int column) {
			this.table = table;
			this.action = action;

			renderButton = new JButton();
			editButton = new JButton();
			editButton.setFocusPainted(false);
			editButton.addActionListener(this);
			originalBorder = editButton.getBorder();
			setFocusBorder(new LineBorder(Color.BLUE));

			TableColumnModel columnModel = table.getColumnModel();
			columnModel.getColumn(column).setCellRenderer(this);
			columnModel.getColumn(column).setCellEditor(this);
			table.addMouseListener(this);
		}

		//
		// Implement ActionListener interface
		//
		/*
		 * The button has been pressed. Stop editing and invoke the custom
		 * Action
		 */
		public void actionPerformed(ActionEvent e) {
			int row = table.convertRowIndexToModel(table.getEditingRow());
			fireEditingStopped();

			// Invoke the Action

			ActionEvent event = new ActionEvent(table,
					ActionEvent.ACTION_PERFORMED, "" + row);
			action.actionPerformed(event);
		}

		@Override
		public Object getCellEditorValue() {
			return text;
		}

		/**
		 * Get foreground color of the button when the cell has focus
		 * 
		 * @return the foreground color
		 */
		public Border getFocusBorder() {
			return focusBorder;
		}

		public int getMnemonic() {
			return mnemonic;
		}

		@Override
		public Component getTableCellEditorComponent(JTable table,
				Object value, boolean isSelected, int row, int column) {
			text = (value == null) ? "Wiki" : value.toString();
			editButton.setText(text);
			return editButton;
		}

		//
		// Implement TableCellRenderer interface
		//
		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) {
			if (isSelected) {
				renderButton.setForeground(table.getSelectionForeground());
				renderButton.setBackground(table.getSelectionBackground());
			} else {
				renderButton.setForeground(table.getForeground());
				renderButton.setBackground(UIManager
						.getColor("Button.background"));
			}

			if (hasFocus) {
				renderButton.setBorder(focusBorder);
			} else {
				renderButton.setBorder(originalBorder);
			}

			renderButton.setText((value == null) ? "Wiki" : value.toString());
			return renderButton;
		}

		public void mouseClicked(MouseEvent e) {
		}

		public void mouseEntered(MouseEvent e) {
		}

		public void mouseExited(MouseEvent e) {
		}

		//
		// Implement MouseListener interface
		//
		/*
		 * When the mouse is pressed the editor is invoked. If you then then
		 * drag the mouse to another cell before releasing it, the editor is
		 * still active. Make sure editing is stopped when the mouse is
		 * released.
		 */
		public void mousePressed(MouseEvent e) {
			if (table.isEditing() && table.getCellEditor() == this)
				isButtonColumnEditor = true;
		}

		public void mouseReleased(MouseEvent e) {
			if (isButtonColumnEditor && table.isEditing())
				table.getCellEditor().stopCellEditing();

			isButtonColumnEditor = false;
		}

		/**
		 * The foreground color of the button when the cell has focus
		 * 
		 * @param focusBorder
		 *            the foreground color
		 */
		public void setFocusBorder(Border focusBorder) {
			this.focusBorder = focusBorder;
			editButton.setBorder(focusBorder);
		}

		/**
		 * The mnemonic to activate the button when the cell has focus
		 * 
		 * @param mnemonic
		 *            the mnemonic
		 */
		public void setMnemonic(int mnemonic) {
			this.mnemonic = mnemonic;
			renderButton.setMnemonic(mnemonic);
			editButton.setMnemonic(mnemonic);
		}
	}

	private static void createAndShowGUI() {
		JMenuBar menuBar;
		JMenu menu;
		JMenuItem menuItem;
		menuBar = new JMenuBar();
		menu = new JMenu("File");
		menu.setMnemonic(KeyEvent.VK_F);
		menu.getAccessibleContext().setAccessibleDescription(
				"The only menu in this program that has menu items");
		menuBar.add(menu);
		menuItem = new JMenuItem("A text-only menu item", KeyEvent.VK_T);
		menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1,
				ActionEvent.ALT_MASK));
		menuItem.getAccessibleContext().setAccessibleDescription(
				"This doesn't really do anything");
		menu.add(menuItem);
		menuBar.add(menu);
		// Create and set up the window.
		
		JFrame frame = new JFrame("Tölvuleikjaskipuleggjari jos16");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		// Create and set up the content pane.
		jozioforrit newContentPane = new jozioforrit();
		newContentPane.setOpaque(true); // content panes must be opaque
		frame.setContentPane(newContentPane);

		// Display the window.
		frame.setJMenuBar(menuBar);
		frame.setLocation(20,20);
		frame.setMinimumSize(new Dimension(480,150));
		frame.pack();
		frame.setVisible(true);
	}

	public static void main(String[] args) {
		createAndShowGUI();
	}

	private JTextField filterText;

	private TableRowSorter<TableModel> sorter;

	private JTable table;

	public jozioforrit() {
		Object rows[][] = {
				{ "Leikurinn", "Veldu tegund úr listanum", "Einkunn", "Bannað?" },
				{ "Prince of Persia", "", "", "" } };
		String columns[] = { "Leikur", "Tegund Leiks", "Einkunn",
				"Aldurshópur", "Um Leikinn"};

		setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		// Create a table with a sorter.
		final DefaultTableModel model = new DefaultTableModel(rows, columns) {
			@Override
			public Class getColumnClass(int column) {
				Class returnValue;
				if ((column >= 0) && (column < getColumnCount())) {
					returnValue = getValueAt(0, column).getClass();
				} else {
					returnValue = Object.class;
				}
				return returnValue;
			}
		};
		sorter = new TableRowSorter<TableModel>(model);
		table = new JTable(model);

		table.setRowHeight(20);
		table.setFont(new Font("Calibri", Font.PLAIN, 13));
		
		table.getColumnModel().getColumn(0).setMinWidth(105);
		table.getColumnModel().getColumn(1).setMinWidth(165);
		table.getColumnModel().getColumn(2).setMinWidth(60);
		table.getColumnModel().getColumn(3).setMinWidth(70);
		table.getColumnModel().getColumn(4).setMinWidth(80);
		
		TableColumn tableColumn = table.getColumnModel().getColumn(1);
		JComboBox comboBox = new JComboBox();
		comboBox.addItem("Hlutverkaleikur");
		comboBox.addItem("Íþróttir");
		comboBox.addItem("Borðspil");
		comboBox.addItem("Fyrstu persónu skotleikur");
		comboBox.addItem("Barnaleikur");
		comboBox.addItem("Ævintýri");
		comboBox.addItem("Herkænskuleikur");
		comboBox.addItem("Púsl og/eða smáleikur");
		comboBox.setEditable(true);
		tableColumn.setCellEditor(new DefaultCellEditor(comboBox));

		TableColumn tableColumn2 = table.getColumnModel().getColumn(2);
		JComboBox comboBox2 = new JComboBox();
		comboBox2.addItem("10");
		comboBox2.addItem("9");
		comboBox2.addItem("8");
		comboBox2.addItem("7");
		comboBox2.addItem("6");
		comboBox2.addItem("5");
		comboBox2.addItem("4");
		comboBox2.addItem("3");
		comboBox2.addItem("2");
		comboBox2.addItem("1");
		comboBox2.setEditable(false);
		tableColumn2.setCellEditor(new DefaultCellEditor(comboBox2));

		TableColumn tableColumn3 = table.getColumnModel().getColumn(3);
		JComboBox comboBox3 = new JComboBox();
		comboBox3.addItem("Leyfilegt öllum");
		comboBox3.addItem("6+");
		comboBox3.addItem("12+");
		comboBox3.addItem("16+");
		comboBox3.addItem("18+");
		comboBox3.setEditable(true);
		tableColumn3.setCellEditor(new DefaultCellEditor(comboBox3));

		JButton button = new JButton("Skrá leik");
		button.setPreferredSize(new Dimension(85, 20));
		button.setBorder(BorderFactory.createEtchedBorder());
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Object[] kuki = new Object[] {"Nýr Leikur", "Tegund"};
				model.insertRow(1,kuki);
			}
		});

		add(button, c);

		table.setRowSorter(sorter);
		table.setPreferredScrollableViewportSize(new Dimension(500, 210));
		table.setFillsViewportHeight(true);
		// single selection
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		Action meira = new AbstractAction() {
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@SuppressWarnings("deprecation")
			public void actionPerformed(ActionEvent e) {
				e.getSource();
				Integer.valueOf(e.getActionCommand());

				JDialog f = new AboutDialog(new JFrame());
				f.show();
			}
		};

		ButtonColumn buttonColumn = new ButtonColumn(table, meira, 4);
		buttonColumn.setMnemonic(KeyEvent.VK_W);
		
		JScrollPane scrollPane = new JScrollPane(table);
		c.anchor = GridBagConstraints.NORTH;
		c.fill = GridBagConstraints.BOTH;
		c.weightx = 1.0;
		c.weighty = 1.0;
		c.gridwidth = 3;
		c.gridx = 0;
		c.gridy = 1;
		add(scrollPane, c);

		JLabel l1 = new JLabel("Leita");
		c.anchor = GridBagConstraints.NORTH;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weighty = 0.0;
		c.gridheight = 1;
		c.gridx = 1;
		c.gridy = 0;
		c.insets = new Insets(0, 100, 0, 0);
		add(l1, c);
		filterText = new JTextField();
		// Whenever filterText changes, invoke newFilter.
		filterText.getDocument().addDocumentListener(new DocumentListener() {
			public void changedUpdate(DocumentEvent e) {
				if (filterText.getText().length() == 0) {
					sorter.setRowFilter(null);
				} else {
					sorter.setRowFilter(RowFilter.regexFilter(filterText
							.getText()));
				}
			}

			public void insertUpdate(DocumentEvent e) {
				if (filterText.getText().length() == 0) {
					sorter.setRowFilter(null);
				} else {
					sorter.setRowFilter(RowFilter.regexFilter(filterText
							.getText()));
				}
			}

			public void removeUpdate(DocumentEvent e) {
				if (filterText.getText().length() == 0) {
					sorter.setRowFilter(null);
				} else {
					sorter.setRowFilter(RowFilter.regexFilter(filterText
							.getText()));
				}
			}
		});
		l1.setLabelFor(filterText);
		c.anchor = GridBagConstraints.NORTH;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weighty = 0.0;
		c.gridheight = 1;
		c.gridx = 2;
		c.gridy = 0;
		c.insets = new Insets(0, 140, 0, 0);
		add(filterText, c);

	}

}

Open in new window

jozioAsked:
Who is Participating?
 
ClintB12Commented:
One way to do this is to create an external file that saves the information using RandomAccessFile and writeChar() or writeInt() to store the data like this example:

      void saveData(int num1, int num2)
      {
            try {
            RAFile = new RandomAccessFile("Data.raf", "rw");

            long len = RAFile.length(); // These lines will append to the end of the file
            int length = (int)len; // These lines will append to the end of the file
            RAFile.seek(len); // These lines will append to the end of the file
            RAFile.writeInt(num1); // This line writes data for an int
            RAFile.writeChar(num2); // This line writes data for an int
            }
            catch (FileNotFoundException ex) {
                  System.out.println(ex.getMessage());
            }
            catch (IOException ex) {
                  System.out.println(ex.getMessage());
            }
      }

Then you need to load the saved info on startup of your program. Here's an example:

      static void loadData()
      {
            data = new int[6];
            DataInputStream dis = null;
            DataOutputStream dos = null;
            File saveFile = new File("Data.raf");
            if (saveFile.exists())
            {
               try
               {
                  dis = new DataInputStream(new FileInputStream(saveFile));
                  for (int i = 0; i < 6; i++)
                       data[i] = dis.readInt();
                  }
               }
               catch (FileNotFoundException ex)
               {
                  System.out.println(ex.getMessage());
               }
               catch (IOException ex)
               {
                  System.out.println(ex.getMessage());
               }
               finally
               {
                  try
                   {
                      if (dis != null) dis.close();
                  }
                  catch (IOException ex)
                  {
                      System.out.println(ex);
                  }
               }
            }
            else { // Here's where you can load your data into the file if it doesn't exist
               try {
                  dos = new DataOutputStream(new FileOutputStream(saveFile));
                  dos.writeInt(2);
                  dos.writeInt(1);
               }
               catch (IOException ex) {
                  System.out.println(ex.getMessage());
               }
               finally {
                  try {
                     if (dos != null) dos.close();
                    }
                     catch (IOException ex) {
                  System.out.println(ex.getMessage());
                  }
               }
            }
      }
0
 
ClintB12Commented:
One more thing, the loadData method in the example is static because it's called inside the main method, public static void main(String[] args). Otherwise, you should be able to drop the "static."
0
 
ClintB12Commented:
Oops! I noticed I used writeChar() on an int value! It should be RAFile.writeInt(num2);
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

 
jozioAuthor Commented:
It looks pretty good, but i'm in a lot of problem inserting it into my code.  I'm pretty new to Java so i'm wondering do i put the void saveData() where i make my DefaultTableModel and then call it after i add a row ? Or what ?... I also do not fully understand how i am saving my data, do I have to change that ?

The tablemaking code is attached.. I think I can figure the loading out if i put the saveData in the right context.

Thank you.. this was very helpful.
public jozioforrit() {
		Object rows[][] = {
				{ "Leikurinn", "Veldu tegund úr listanum", "Einkunn", "Bannað?" },
				{ "Prince of Persia", "", "", "" } };
		String columns[] = { "Leikur", "Tegund Leiks", "Einkunn",
				"Aldurshópur", "Um Leikinn"};

		setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		// Create a table with a sorter.
		final DefaultTableModel model = new DefaultTableModel(rows, columns) {
			@Override
			public Class getColumnClass(int column) {
				Class returnValue;
				if ((column >= 0) && (column < getColumnCount())) {
					returnValue = getValueAt(0, column).getClass();
				} else {
					returnValue = Object.class;
				}
				return returnValue;
			}
		};
		sorter = new TableRowSorter<TableModel>(model);
		table = new JTable(model);

		table.setRowHeight(20);
		table.setFont(new Font("Calibri", Font.PLAIN, 13));


// And here i add a row

JButton button = new JButton("Skrá leik");
		button.setPreferredSize(new Dimension(85, 20));
		button.setBorder(BorderFactory.createEtchedBorder());
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Object[] kuki = new Object[] {"Nýr Leikur", "Tegund"};
				model.insertRow(1,kuki);
			}
		});

Open in new window

0
 
ClintB12Commented:
Okay, you could put the two methods I gave you at the end of your code, for example, then you call them at the appropriate time within the rest of the code like this:

loadData();

saveData(1, 2);

Remember, these are just examples, and to work with your code will need to be rewritten for a custom-fit. I would use the loadData() method either right before you fill up the JTable with the entries it will read from the file or else you could also add the JTable values loading code in the loadData() method itself. You could put the default table values in the "else" section I marked which will only be executed if the data.raf file doesn't exist.

(As a side note, you can call that file whatever you want, and the extension could be .txt, for example, which is already associated with Notepad for easy viewing, but you cannot edit the information with notepad or you will get gobbledy-gook when it tries to load via the loadData() method! The data must be altered via the saveData() method. Another tip would be to use the RAFile.seek(0); to start writing at the beginning of the file, in other words, overwriting the preexisting data if that's what you need your program to do.)

As for the saveData() method, call it at an appropriate time, like right before the program exits, or you could create a Save button that calls saveData().

For more details on the constructors, an invaluable resource for Java programmers exists at: http://java.sun.com

Use of RandomAccessFile:
http://java.sun.com/j2se/1.5.0/docs/api/java/io/class-use/RandomAccessFile.html

I'm using an older version of Java, 1.4.2. If the saveData() method I gave you won't compile, let me know. It can be rewritten using the RAF constuctors. I included both because there is more than one way to access, write and read from external data files.
0
 
jozioAuthor Commented:
Thank you very much for your help, but I can't find out how to put this in my code, i don't know if I will have to ruin all that I've done before  to make this feature work.  I only have like 2 months programming experience so I'm pretty stupid :).  If it's easy it would be nice if you could put like an example inside my code. I'll Accept the above as a solution...

kv. Jón Orri Sigurðarson
0
 
ClintB12Commented:
I'll get back to you on that ASAP, but right now I've got to go to work.
0
 
jozioAuthor Commented:
That would be super. thanks.
0
 
jozioAuthor Commented:
Well, I do not need it anymore. thx anyways.
0
 
ClintB12Commented:
Sorry, I was very busy today. Were you able to insert it into your code and get it all to work?
0
 
jozioAuthor Commented:
Nope :/,  I think I'll just turn it in(it's a school project) like it is :)....

If it is easy for you to put it in the code it would be very helpful... But really don't bother if it's difficult... Thx,

kv Jón Orri Sigurðarson
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.