views:

2369

answers:

4

I have a JFrame that contains a "display" JPanel with JTextField and a "control" JPanel with buttons that should access the contents of the display JPanel. I think my problem is related on how to use the observer pattern, which in principle I understand. You need to place listeners and update messages, but I don't have a clue where to put these, how to get access from one panel to the other and maybe if necessary to introduce a "datamodel" class. For example, I want to access the contents of the JTextField from the control panel and I use an anonymous action listener as follows:

JButton openfile = new JButton("Convert file");
openfile.addActionListener(new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
             openButtonPressed();
           }

         } );
+1  A: 

It does make the code cleaner if you create the models in one layer and add a layer or two above to create the components and layout. Certainly do not extend the likes of JFrame and JPanel.

Do not feel the need to make the composition hierarchy in the model layer exactly match the display. Then it's just a matter of taking the text from the Document and performing the relevant operation.

Okay, perhpas not that simple. Swing models are a little bit messy. In particular ButtonModel is brain damaged, and the controller area of code might not be entirely pure.

Tom Hawtin - tackline
A: 

We have so called builders, which will build the parent panel out of the children. In this builder you will have access to all the subcomponents you need to listen to and can thus can implement any logic there.

Finally the builder will then return the parent panel with the complete logic.

Once you've got the parent panel it's really a mess getting to the child components and have them do anything.

boutta
A: 

thanks. I added a datamodel layer which handles somehow the communication between the panels.

I also found this link on Listeners on JTextField usefull:

link text

poseid
+1  A: 

You need to reduce the coupling between these objects.

You can have a master object, that owns all the text fields and the button ( the panels are irrelevant )

Then a separete actionlistener within that master object ( I call it mediator see mediator pattern )

That action listener performs a method on the mediator which in turn take the values from the textfields and create perhaps a transfer object.

This way you reduce the coupling between the panels, textfields etc. and let the control in one place ( the mediator ) that is, you don't let them know each other.

You can take a look at the code in this question: http://stackoverflow.com/questions/324554/#324559

It shows these concepts in running code.

BTW the observer pattern is already implemented in the JTextField, JButton, ActionListener etc. You just need to add the hooks.

I hope this helps.

EDIT Joined two answers into one.

This is the code.

class App { // this is the mediator

    // GUI components.
    private JFrame frame;
    private JTextField name;
    private JTextField count;
    private JTextField date;
    // Result is displayed here.
    private JTextArea textArea;

    // Fired by this button.
    private JButton   go;

    private ActionListener actionListener;


    public App(){
        actionListener = new ActionListener(){
            public void actionPerformed( ActionEvent e ){
                okButtonPressed();
            }
        };
    }

    private void okButtonPressed(){
         // template is an object irrelevant to this code.
         template.setData( getData() );
         textArea.setText( template.getTransformedData() );
    }


    public void initialize(){

        frame     = new JFrame("Code challenge v0.1");
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        name     = new JTextField();
        count    = new JTextField();
        date     = new JTextField();
        textArea = new JTextArea();
        go       = new JButton("Go");
        go.addActionListener( actionListener ); // prepare the button.

        layoutComponents(); // a lot of panels are created here. Irrelevant.
    }
}

Complete and running code can be retrieved here:

It is important to favor composition over inheritance when possible.

OscarRyz