The document describes an implementation of the Observer pattern using four Java classes - Data, TextFrame, BarGraph, and MouseAdapter.
Data is the model that holds the bar graph data and notifies observers of changes. TextFrame and BarGraph are observer views that update when the model changes. TextFrame displays the data values and BarGraph displays the bar graph. MouseAdapter handles mouse clicks on the bar graph to allow modifying the data.
When the user enters a new value in TextFrame, it updates Data. Data then notifies BarGraph and TextFrame of the change. When the user clicks a bar in BarGraph, MouseAdapter modifies the data in Data. Data again notifies the observers of the change
5. Observer Pattern Times Four:
JTextField: ActionListener receives event after you hit <return>.
The ActionListener updates the Data (Model) object.
JTextField
ActionListener
addActionListener
actionPerformed
anonymous
object
6. Observer Pattern Times Four:
Data: Is observed by the BarGraph (ChangeListener) for any
changes to the model.
Data
ChangeListener
attach
stateChanged
BarGraph
7. Observer Pattern Times Four:
BarGraph: MouseListener receives event when you click on the
bar graph.
mousePressed() moves the bar and updates Data object.
BarGraph
MouseListener
addMouseListener
mousePressed
Mouse
Adapter
8. Observer Pattern Times Four:
Data: Is observed by TextFrame (ChangeListener) for any
changes to data.
Data
ChangeListener
attach
stateChanged
TextFrame
12. Data.java
public class Data {
public Data(ArrayList<Double> d)
{
data = d;
listeners = new ArrayList<ChangeListener>();
}
public ArrayList<Double> getData()
{
return (ArrayList<Double>) (data.clone());
}
public void attach(ChangeListener c)
{
listeners.add(c);
}
}
13. Data.java
public class Data {
public void update(int loc, double val)
{
if (val > MAX)
val = MAX;
if (val < 0)
val = 0;
data.set(loc, new Double(val));
// for each listener, let the listener know a change has occurred
for (ChangeListener l : listeners)
{
l.stateChanged(new ChangeEvent(this));
}
}
public Double get(int i) {
return data.get(i);
}
private ArrayList<Double> data;
private ArrayList<ChangeListener> listeners;
public static final double MAX = 100.0;
}
14. TextFrame:
public class TextFrame extends JFrame implements ChangeListener {
public TextFrame (Data md) {
d = md;
ActionListener l = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JTextField c = (JTextField) e.getSource();
int ndx = findBox(c);
if (ndx >= 0)
d.update(ndx,Double.parseDouble(c.getText().trim()));
}
};
JPanel tPanel = new JPanel();
tPanel.setLayout(new BoxLayout(tPanel,BoxLayout.PAGE_AXIS));
...
}
}
tf = new JTextField[5];
for (int i = 0; i < 5; i++) {
tf[i] = new JTextField(10);
tf[i].addActionListener(l);
tPanel.add(tf[i]);
}
add(tPanel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
15. TextFrame:
@Override
public void stateChanged(ChangeEvent e) {
// how I notify the text frame if the bar graph changes
for (int i = 0; i < 5; i++){
double d1 = d.get(i).doubleValue();
String s = tf[i].getText().trim();
double d2;
try {
d2 = Double.parseDouble(s);
} catch(NumberFormatException nfe ) {
d2 = 0.0;
}
if (Math.abs(d1 - d2) > 0.01)
tf[i].setText(new Double(d1).toString());
}
}
public int findBox(JTextField t) {
int i = 0;
while (i < 5) {
if (t == tf[i])
return i;
i++;
}
return -1;
}
}
private Data d;
private JtextField[ ] tf;
16. BarGraph:
public class BarGraph extends JFrame implements ChangeListener {
public BarGraph(Data md) {
d = md;
setLocation(0,300);
Icon barIcon = new Icon() {
public int getIconWidth() { return WIDTH; }
public int getIconHeight() { return HEIGHT; }
}
public void paintIcon(Component c, Graphics g , int x, int y) {
Graphics2D g2 = (Graphics2D) g;
Color cl = g2.getColor();
for (int i = 0; i < 5; i++) {
Rectangle2D.Double rectangle =
new Rectangle2D.Double(0,
(HEIGHT/6)*i,
WIDTH*(d.get(i).doubleValue()/Data.MAX),
(HEIGHT/6));
g2.setPaint(Color.cyan);
g2.fill(rectangle);
g2.setColor(Color.black);
g2.draw(rectangle);
}
Rectangle2D.Double rectangle =
new Rectangle2D.Double(0,375,WIDTH,(HEIGHT/6));
g2.setPaint(cl); g2.fill(rectangle);g2.setColor(cl);g2.draw(rectangle);
}
}; // end of barIcon panel
...
17. BarGraph:
public class BarGraph extends JFrame implements ChangeListener {
public BarGraph(Data md) {
...
add(new JLabel(barIcon));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MouseListener m = new MouseAdapter() {
public void mousePressed(MouseEvent e){
Point2D p = e.getPoint();
double dy = p.getY();
int barToMove = (int)(dy / BARHEIGHT);
if (barToMove < 0 || barToMove > 4)
return;
double dx = p.getX();
double newV = (dx/WIDTH)* Data.MAX;
d.update(barToMove, newV);
}
};
addMouseListener(m);
pack();
setVisible(true);
} // end constructor
} // end class