// patterns/visualobserver/BoxObserver.java // (c)2016 MindView LLC: see Copyright.txt // We make no guarantees that this code is fit for any purpose. // Visit http://mindviewinc.com/Books/OnJava/ for more book information. // Demonstration of Observer pattern using // Java's built-in observer classes. // {TimeOut:4000} During testing package patterns.visualobserver; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import onjava.MouseClick; // You must inherit a new type of Observable: class BoxObservable extends Observable { @Override public void notifyObservers(Object b) { // Otherwise it won't propagate changes: setChanged(); super.notifyObservers(b); } } public class BoxObserver extends JFrame { Observable notifier = new BoxObservable(); public BoxObserver(int grid) { setTitle("Demonstrates Observer pattern"); Container cp = getContentPane(); cp.setLayout(new GridLayout(grid, grid)); for(int x = 0; x < grid; x++) for(int y = 0; y < grid; y++) cp.add(new OCBox(x, y, notifier)); } public static void main(String[] args) { int grid = 8; if(args.length > 0) grid = Integer.parseInt(args[0]); JFrame f = new BoxObserver(grid); f.setSize(500, 400); f.setVisible(true); f.setDefaultCloseOperation(DISPOSE_ON_CLOSE); } } class OCBox extends JPanel implements Observer { Observable notifier; int x, y; // Locations in grid Color cColor = newColor(); static final Color[] colors = { Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow }; static Color newColor() { return colors[ (int)(Math.random() * colors.length) ]; } OCBox(int x, int y, Observable notifier) { this.x = x; this.y = y; notifier.addObserver(this); this.notifier = notifier; addMouseListener((MouseClick) e -> notifier.notifyObservers(OCBox.this)); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(cColor); Dimension s = getSize(); g.fillRect(0, 0, s.width, s.height); } @Override public void update(Observable o, Object arg) { OCBox clicked = (OCBox)arg; if(nextTo(clicked)) { cColor = clicked.cColor; repaint(); } } private boolean nextTo(OCBox b) { return Math.abs(x - b.x) <= 1 && Math.abs(y - b.y) <= 1; } }