简单的例子
回到本文一开始的那个Explorer的例子,我们考虑做一个简单的图片浏览器,使树型选择组件和图片浏览面板在两个不同的类中,其中图片浏览面板根据所选择的树的节点显示相应的图片,所以图片浏览面板是一个observer,树是subject。由于Java单根继承的原因,我们不能同时继承JPanel和Observable,但可以用对象的组合把一个subject放到我们的类当中,并通过TreeSelectionListener触发subject的setChanged方法,并通过notifyObservers方法通知observer。
例子代码如下:
//LeftPanel.java package com.jungleford.test; import java.awt.BorderLayout; import javax.swing.*; import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.tree.DefaultMutableTreeNode; import java.util.Observable; import java.util.Observer; public final class LeftPanel extends JPanel {// 把树型选择视图布局在左边 private JTree tree;// 树型选择视图 private JScrollPane scroll;// 让视图可滚动 private DefaultMutableTreeNode root, node1, node2;// 根节点及两个叶子 private Sensor sensor;// sensor是一个Observable,由于只能单根继承,所以作为组合成员 private String file;// 图片文件名,与RightPanel通信的内容 public LeftPanel(Observer observer) { file = ""; sensor = new Sensor(); sensor.addObserver(observer);// 向Observable注册Observer root = new DefaultMutableTreeNode("Images"); tree = new JTree(root); node1 = new DefaultMutableTreeNode("Rabbit"); node2 = new DefaultMutableTreeNode("Devastator"); root.add(node1); root.add(node2); tree.addTreeSelectionListener(new TreeSelectionListener() {// 树节点选择动作 public void valueChanged(TreeSelectionEvent e) { Object obj = e.getPath().getLastPathComponent(); if (obj instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)obj; if (node == root) file = "";// 选择根 if (node == node1) file = "rabbit.jpg";// 选择node1 if (node == node2) file = "devastator.gif";// 选择node2 sensor.setData(file);// 改变Observable sensor.notifyObservers();// 通知observer,对象已改变 } } }); scroll = new JScrollPane(tree); add(scroll, BorderLayout.CENTER); } public Observable getSensor() {// 返回Observable对象,使Observer可以获取 return sensor; } } class Sensor extends Observable {// 定义自己的Observable private Object data; public void setData(Object newData) { data = newData; setChanged();// 改变Observable System.out.println("Data changed!"); } public Object getData() { return data; } } //RightPanel.java package com.jungleford.test; import java.awt.*; import javax.swing.JPanel; import java.util.Observer; import java.util.Observable; public class RightPanel extends JPanel implements Observer {// 把图片浏览视图布局在右边 private Image image; public void update(Observable subject, Object obj) {// 定义接收到Observable变化后的响应动作 String file = (String)((Sensor)subject).getData(); if (!file.equals("")) { image = Toolkit.getDefaultToolkit().getImage(file); MediaTracker tracker = new MediaTracker(this);// 定义图像跟踪 tracker.addImage(image, 0); try { tracker.waitForID(0);// 等待图像的完全加载 } catch (InterruptedException e) { e.printStackTrace(); } } else image = null; repaint();// 重绘组件 }