0

I've a main frame on which there is a side panel with some buttons, and central panel used to display the tables and data generated from buttons on the side panel and its sub-panels On the start my central panel is blank and I want it to always return to its initial state( blank ) after each click on a button before generating any data

I've use some sort of observer pattern (I'm not so experienced) but my problem is that the central panel must display data after clicks on some buttons that are on panels that also need a click on the side panel before to be generated

I've tried to make an executable example on the following classes, my real application displays some tables on the central panel and i send the models via the update method of the observers

hope its clear for you and I hope if you can really help me

1 - the main frame:

package tests;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame; 
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class MainFrame extends JFrame implements MyObserver{

private SidePanel sidePanel;
private JPanel centralPanel;
private JFrame frame;
private JLabel title;

public MainFrame(){
    frame = new JFrame("TEST");
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setLayout(new BorderLayout());

    sidePanel = new SidePanel();
    sidePanel.addObserver(this);
    centralPanel = new JPanel();
    title = new JLabel();

    initialise(0);

    frame.pack();
    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
}

private void initialise(int i) {
    if( i == 0){
        centralPanel.setPreferredSize(new Dimension(400,300));
        centralPanel.setBackground(Color.green);
        title.setText("GREEN");

        centralPanel.add(title, BorderLayout.CENTER);

        frame.add(sidePanel, BorderLayout.WEST);
        frame.add(centralPanel, BorderLayout.CENTER);
    }
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            new MainFrame();
        }
    });
}

@Override
public void update(int color) {
    if(color == 0){
        centralPanel.setBackground(Color.yellow);
        title.setText("YELLOW");
    }else{
        centralPanel.setBackground(Color.pink);
        title.setText("PINK");
    }
}
}

2 - The side Panel

package tests;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;

public class SidePanel extends JPanel implements MyObserver,MyObservable{
private JPanel panel;
private JButton test;
private MyObserver observer;
private ButtonPanel buttonPanel;

public SidePanel(){
    panel = new JPanel();
    panel.setPreferredSize(new Dimension(140, 300));
    panel.setBackground(Color.blue);
    panel.setLayout(new BoxLayout(panel, 0));


    test = new JButton("Lunch buttons");
    test.setPreferredSize(new Dimension(80,30));
    buttonPanel = new ButtonPanel();
    buttonPanel.addObserver(this);
    test.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            buttonPanel.setVisible(true);

        }
    });

    panel.add(Box.createVerticalGlue());
    panel.add(test);
    panel.add(Box.createVerticalGlue());

    panel.setVisible(true);
    this.add(panel, BorderLayout.CENTER);
}

@Override
public void addObserver(MyObserver obs) {
    this.observer = obs;
}

@Override
public void updateObserver(MyObserver obs, int color) {
    obs.update(color);
}

@Override
public void update(int color) {
    updateObserver(observer, color);
}


}

3 - the buttons panel, generally the source of any data to be displayed on the central panel

package tests;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;

public class ButtonPanel extends JDialog implements MyObservable{
private JButton yellow;
private JButton orange;
private JPanel panel;
private MyObserver observer;

public ButtonPanel(){
    panel = new JPanel();
    panel.setPreferredSize(new Dimension(300, 40));
    panel.setLayout(new FlowLayout());
    this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    this.setContentPane(panel);

    yellow = new JButton("YELLOW");
    yellow.setPreferredSize(new Dimension(100,30));
    yellow.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            updateObserver(observer, 0);
        }
    });

    orange = new JButton("ORANGE");
    orange.setPreferredSize(new Dimension(100,30));
    orange.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            updateObserver(observer, 1);
        }
    });

    panel.add(yellow);
    panel.add(orange);

    pack();
    setLocationRelativeTo(null);
}

@Override
public void addObserver(MyObserver obs) {
    this.observer = obs;
}

@Override
public void updateObserver(MyObserver obs, int color) {
    obs.update(color);
}
}

Finally, the customized observer and observable interfaces, note in the real app i use a table model not just an int - I'm not sure it's a good way -

package tests;

public interface MyObservable {
public void addObserver(MyObserver obs);
public void updateObserver(MyObserver obs, int color);
} 

package tests;

public interface MyObserver {
public void update(int color);
}
Ouldnah
  • 21
  • 4
  • 1
    Apart from what is the actual question, consider taking a look at [How to Use CardLayout](http://docs.oracle.com/javase/tutorial/uiswing/layout/card.html) – MadProgrammer Feb 08 '15 at 23:56
  • 1
    ` panel.setPreferredSize(new Dimension(300, 40));` See [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?](http://stackoverflow.com/q/7229226/418556) (Yes.) – Andrew Thompson Feb 09 '15 at 00:50
  • @MadProgrammer, Thanks it will solve a part of my problem, But for the observer-pattern do you think that my method is correct ie. To use the update method to transfer some data between classes, and to observe a class via many other classes also is it normal that a class be observed and to be observer at the same time I need a design concept criticism on these issues – Ouldnah Feb 09 '15 at 10:57
  • @Andrew_Thompson Personally I always have mush problems with them but I’m not sure if they can be avoided completely even if I use a powerful LayoutManager – Ouldnah Feb 09 '15 at 10:57
  • @Ouldnah Note that adding an underscore into my name after the `@` means I **don't** get notified. *"not sure if they can be avoided completely"* The point is though, that if absolutely required, we should `@Override` the method in question. Never, *ever,* **ever,** ***ever*** is it a good idea to call the `set` version. *"even if I use a powerful LayoutManager"* I think kleopatra as well as many others would disagree with that - though they are referring to 3rd party layout managers. – Andrew Thompson Feb 09 '15 at 20:54
  • @AndrewThompson, First excuse me for adding the underscore it was just a mistake; Second I'll learn from your answer I'm some how new in the swing world...Could you give me an example on overriding a method to define a preferred size – Ouldnah Feb 09 '15 at 22:22
  • *"it was just a mistake"* No problem. :) We all make mistakes. ;) – Andrew Thompson Feb 09 '15 at 23:33

1 Answers1

0

CHANGED ANSWER:

In SidePanel.java add:

private MainFrame frame;

Then make your constructor take a MyFrame object as parameter. Do this:

public SidePanel(MainFrame frame){
    this.frame = frame;
    //rest not changed
    //
}

Change the actionPerformed() of test button to:

test.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent arg0) {
        buttonPanel.setVisible(true);
        frame.initialise(0);    // this line is added
    }
});

In MainFrame.java:

Change sidePanel = new SidePanel(); to sidePanel = new SidePanel(this);

AND

Change private void initialise(int i) to public void initialise(int i)

This does what you are trying to achieve.

Minar Mahmud
  • 2,577
  • 6
  • 20
  • 32
  • I guess the windowClosing event will be fired only if I close the new button panel directly will I need the centralPanle to keep displaying the data till I click again on the button – Ouldnah Feb 10 '15 at 11:03
  • I have changed the answer. This is what you need to do. I couldnt get you earlier. Sorry for that. – Minar Mahmud Feb 10 '15 at 13:41
  • ok brother its working on both your method and on MadProgrammer hint by using the cardLayout. I'll post my detailed solution soon – Ouldnah Feb 10 '15 at 22:12