技术开发 频道

利用Observer模式解决组件间通信问题

     简单的例子

    回到本文一开始的那个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();// 重绘组件   }


  

0
相关文章