tags:

views:

220

answers:

5

Say, an application properties page with lots of JCheckboxes, JTextfields, JLists and other JComponents. Now, what I need to do is track the changes user makes and save them. What would be the correct way of implementing this?

A: 

A Command class and a serializable ArrayList or LinkedList of Commands. Commands would be generated in the actionPerformed method(s).

Yeah, but just typing into a JTextfield won't generate ActionEvents.
alex
Isn't there an event handler for typing into text fields though? all you need is an abstract command class and subclasses like TypingCommand, CheckboxCommand, etc, etc. At least that's that I'd do
+2  A: 

You don't need to track changes in real times (unless special needs).

You can react on the OK button, iterating on the components, getting their value, perhaps comparing with the old one or just saving all the values blindly.
And of course abandon everything if the user cancels.

PhiLho
Agree, will keep it simple.
alex
+1  A: 

Two approaches you can use:

(1) When the user clicks OK on your properties page, pull the current values out of your JComponents and update your settings or whatnot. This is the easiest method as you don't need ActionListeners and if the user backs out you don't have to roll back changes (from your question it's not entirely clear what this dialog/page does, though).

(2) For swing objects that implement ActionListener, listen for the ActionEvent and process the changes accordingly. For JTextFields, use a DocumentListener as in the sample code below:

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class Test implements DocumentListener
{
  private JTextField jtf;

  public static void main(String[] args)
  { 
    javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
          public void run()
          {
            Test test = new Test();
          }
        });
  }
  public Test()
  {
    JFrame jf = new JFrame();
    JPanel jp = new JPanel();
    jtf = new JTextField();
    jtf.getDocument().addDocumentListener(this);
    jp.setLayout(new BorderLayout());
    jp.add(jtf, BorderLayout.CENTER);
    jf.add(jp);
    jf.setSize(200, 100);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.setVisible(true);
  }

  public void changedUpdate(DocumentEvent e) 
  {
   // Do stuff here
  }
  public void insertUpdate(DocumentEvent e) 
  {
    // Do stuff here
  }
  public void removeUpdate(DocumentEvent e) 
  {
    // Do stuff here
  }
}

As you might guess from (1), the challenge from (2) comes about if the user backs out and you have to think about how you're going to roll back any changes. It really depends on what you're doing, though.

Catchwa
A great answer, thanks.
alex
+1  A: 

Observer Pattern should help with this. Basically it allows a component (The publisher) to notify other components (subscribers) of things, basically it is an ActionListener (like Catchwa's Answer).

Java Example of Observer Pattern from Google

If you can check out chapter 2 of Head First Design Patterns or the Action Listener Tutorial

I hope that helps a little bit, I can't whip up an example at the moment but hopefully that will help get you started.

edwardTheGreat
A: 

The main question i have is, what changes/events you want to log. Clicks, Text changes, button States, ....

For every event you can add listeners to the swing components. One singleton class could be an implementor of the listeners you want to add to the different components. these singleton class you can add to the different components.

When the component changes or notify a special listener, the singleton manager is notified and can handle this event.

The manager can log the events which are coming in and also save an EventObject, which contains everything you want to store. A list of EventObjects you can store at the disk using xstream.

Markus Lausberg