In OOP programming beginners often wonder how objects on a form talk to their owners. You could give every object a reference to it's owner, but that gets real messy real quick. Instead, you give an object the ability to raise a flag to anyone who wants to listen. In this way, the controls on a form can notify the form of changes without needing to know anything about the form. "Loosly coupled" is your friend.
To avoid complexity, I used one of the mechanisms already in place, the ActionListener. This is a kind of observer pattern, but you rely on the observable elements to support a method of registration, in this case the standard addActionListener.
You could go nuts and have all the elements of the form listen to all the other elements of the form. It's more chaotic, but if the mechanism was in place, it might be simple...
Ok, riffing off of CasiOo's idea, here's a bunch of object that are chat happy.
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
interface GenericObserver<T, E> {
public void update(T sender, E data);
}
interface GenericObservable<T, E> {
public void addObserver(GenericObserver<T, E> observer);
public void removeObserver(GenericObserver<T, E> observer);
}
interface LightPosition {
int getRow();
int getCol();
}
interface LightState {
boolean isOn();
}
class Light extends JButton
implements GenericObservable<LightPosition, LightState>,
GenericObserver<LightPosition, LightState>
{
private final int row, col;
private final java.util.List<GenericObserver<LightPosition, LightState>> listeners;
private boolean lit;
public Light(int row, int col) {
this.listeners = new java.util.ArrayList<GenericObserver<LightPosition, LightState>>();
this.row=row;
this.col=col;
this.setLight(false);
this.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
toggleState();
LightPosition pos = getPosition();
LightState state = getState();
for(GenericObserver<LightPosition, LightState> item : listeners) {
item.update(pos, state);
}
}
});
}
public LightState getState() {
return new LightState() { public boolean isOn() { return lit; } };
}
public LightPosition getPosition() {
return new LightPosition() {
public int getRow() { return row; }
public int getCol() { return col; }
};
}
public void setLight(boolean value) {
this.lit = value;
this.setBackground(this.lit ? Color.YELLOW : Color.BLACK);
}
public void toggleState() { setLight(!this.lit); }
private boolean isNeightbor(LightPosition pos) {
if (pos.getCol()==this.col-1 && pos.getRow()==this.row) { return true; }
if (pos.getCol()==this.col+1 && pos.getRow()==this.row) { return true; }
if (pos.getCol()==this.col && pos.getRow()==this.row-1) { return true; }
if (pos.getCol()==this.col && pos.getRow()==this.row+1) { return true; }
return false;
}
public void update(LightPosition pos, LightState state) {
if (isNeightbor(pos)) { this.toggleState(); }
}
public void addObserver(GenericObserver<LightPosition, LightState> observer) {
this.listeners.add(observer);
}
public void removeObserver(GenericObserver<LightPosition, LightState> observer) {
this.listeners.remove(observer);
}
}
public class Lights extends JFrame {
private final int ROWS = 5, COLS = 5;
private final Light [] cells;
public Lights() {
cells = new Light[ROWS * COLS];
setLayout(new GridLayout(ROWS,COLS,0,0));
setBackground(Color.green);
int count = 0;
for(int row=0; row<ROWS; row++) {
for(int col=0; col<COLS; col++) {
Light b = new Light(row, col);
this.cells[count++] = b;
this.add(B)/>;
}
}
// wire them up
for(int i=0; i<count; i++) {
Light cell = this.cells[i];
for(int j=0; j<count; j++) {
if (i!=j) {
cell.addObserver(this.cells[j]);
}
}
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500,500);
}
private void setLit(int row, int col, boolean value) {
this.cells[row * COLS + col].setLight(value);
}
}
Note, the main form actually doesn't get involved with handling the clicks. The buttons just talk to each other, even though they don't know who they are talking to.

New Topic/Question
Reply





MultiQuote



|