`
yunhaifeiwu
  • 浏览: 161273 次
  • 性别: Icon_minigender_1
  • 来自: 宁波
社区版块
存档分类
最新评论

无限分割面板,并略谈组合模式,顺谈数据结构中的链表

    博客分类:
  • java
阅读更多
先看无限分割面板的效果图(请原谅我没考虑美观)




当在设计时发现:一个对象A有对象B,对象B中又有对象C……,并且这些对象操作相同时,可以使用组合模式。简单实现是:设计一个类,允许把该类的其他实例注入进去。 如果要按GOF中的组合模式设计,请自已参照相关代码,设计一些抽象类或接口等。

举例:
下面中的A类,就是一个简化了的组合模式。属性a与add方法,表明了,该类A允许注入本类的其他实例。如果你把属性a写成List 或Map时,可允许注入多个本类的其他实例。如果要用完整版的组合模式,请参见GOF的组合模式例子。
   public class CombinationModelTest {
    //在这里可以看出,可把A当作 数据结构之链表中的一个节点。
    //里面的属性a可看作是存储下一个节点的指针。于是,数据结构可以很快的用在
    //面向对象中了。 注意:本例旨在讲简化的组合模式实现,并没有列链表操作。
    // 相应的代码实现,读者自行参照数据结库相应实现。
    class A {
        private  String name;
        public A (String name){
            this.name=name;
        }
        A a;//当然了,你可以使用List ,或Map之类的进行存储,不是非得用变量保存
        public void add(A a){
            this.a=a;
        }
        public void remove(){
            this.a=null;
        }
        public void operate (){
            System.out.println("对象"+name+" 的操作。");
        }
        public A getNext(){
            return this.a;
        }
    }
    public void run(){
        A a=new A("a");
        A b=new A("b");
        a.add(b);
        A c=new A("c");
        b.add(c);
        b=new A("d");
        c.add(b);
        
        while (a!=null){
            a.operate();
            a=a.getNext();
        }
        
    }
    public static void main(String args[]) {
         CombinationModelTest dd =new CombinationModelTest();
         dd.run();
        
    }
}


测试运行结果:
引用
对象a 的操作。
对象b 的操作。
对象c 的操作。
对象d 的操作。

一个应用举例:
在设计中,由于要通过panel展现多种属性,而这些panel的或上下或左右可以移动,且个数不清楚。Panel中有可能还会再套一个属性,等等。 又由于为了简化使用,希望每一个panel中,都可以很快的访问到其他panel。
简化需求即得:
   设计一个面板,该面板可以对其间指定的面板进行分割一个,并在新分割中增加指定面板;这个面板任一个子面板都可以访问到其他子面板或根面板。

下面就是一个满足此要求的无限分割面板。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SpringLayout;

/**
 * 基于二分分割所做的 无限次分割面板。<br/>
 * 对已经存在的面板,新添一个分割,并填入指定panel.<br>  
 * 组合模式---当在设计时,如果一个对象A中有对象B,B中又有C,等等,而这些对象<br>
 * 操作都相同,可以用组合模式。简化实现是:设计一个类,允许把该类型的其他有限个实<br>
 * 例注入进去。<br>
 * 
 * 
 * @author cloud
 */
public class FSplitPanel extends JPanel {
    //所有子组件,都存放于Map中。在新增时自动维护。 
    
   private int interval =3;
    
    
    public static final int HORIZONTAL_SPLIT=JSplitPane.HORIZONTAL_SPLIT;
    public static final int VERTICAL_SPLIT=JSplitPane.VERTICAL_SPLIT;
    private class UnitData {
        public  boolean isFree=true;
        private JPanel panel;
        private String name;          
        private JSplitPane parent; 
        private boolean isFirst=false;
        public UnitData(){};
        public UnitData( boolean isFree){ this.isFree=isFree;};
        
    }
    private FSplitPanel root;
 
    private Map<String,UnitData> componentMap=new HashMap<String,UnitData>();
    
 
    public FSplitPanel(){     
        this.root=this;
        UnitData data=new UnitData();
       
        data.name="root";
        data.panel=null;    
        componentMap.put("root", data);         
      
    }
    
    /**
     * 在指定且已经存在的分割中,新增一个分割。并在新得到分割区域中,加入指定panel。
     * @param parent ----指定且已经存在的分割。
     * @param name ------对新得到的分割进行定义。
     * @param panel ------要用该panel去填充新分割
     * @param splitSyle ----分割方向,方平分割还是竖直分割。
     * @return true ---true,分割成功;false,分割失败。
     */
    public boolean  add(String parent,String name,JPanel panel,int splitSyle){
        UnitData data=componentMap.get(parent);        
        if (data==null) return false;
        if (parent.equals("root") && (data.parent!=null ) ) 
            return false;
        
        if (parent.equals("root")){
            SpringLayout layout = new SpringLayout();
            this.setLayout(layout);
            data.isFree=false;
            data.name=name;
            data.panel=panel ;
            data.isFirst=true;                    
            this.add(panel);
            layout.putConstraint(SpringLayout.WEST, panel, interval, SpringLayout.WEST, this);
            layout.putConstraint(SpringLayout.EAST, this, interval, SpringLayout.EAST,panel );
            layout.putConstraint(SpringLayout.NORTH, panel, interval, SpringLayout.NORTH, this);
            layout.putConstraint(SpringLayout.SOUTH, this, interval, SpringLayout.SOUTH, panel);
            

            componentMap.put(name, data);
        } else {
            //当节点不为空,在当前节点使用JSplitPanel分割,并把当前结点,存放到
            //JSplitPanel的左分割中。其右割存放新增的节点            
            
            JSplitPane  splitPanel=new JSplitPane (splitSyle);
            splitPanel.setBorder(null);
             
            if (data.parent==null){
                data.parent=splitPanel; 
                Container  c=data.panel.getParent();
                c.removeAll();
                
                 
                if (data.isFirst){
                    SpringLayout layout = new SpringLayout();
                    c.setLayout(layout);                     
                    c.add(splitPanel);
                    layout.putConstraint(SpringLayout.WEST, splitPanel, interval, SpringLayout.WEST, c);                    
                    layout.putConstraint(SpringLayout.EAST, c, interval, SpringLayout.EAST, splitPanel);
                    layout.putConstraint(SpringLayout.NORTH, splitPanel, interval, SpringLayout.NORTH,c );
                    layout.putConstraint(SpringLayout.SOUTH, c, interval, SpringLayout.SOUTH, splitPanel);

                } else {
                    c.add(splitPanel);
                }               
                splitPanel.setLeftComponent(data.panel);  
                
                UnitData tempData=new UnitData();
                tempData.isFree=false;
                tempData.panel=panel;
                tempData.name=name;     
                tempData.parent=splitPanel;
                splitPanel.setRightComponent(panel);
                componentMap.put(name, tempData);

            } else {
                Component  c=data.parent.getLeftComponent();
                data.parent.setLeftComponent(splitPanel); 
                splitPanel.setLeftComponent(c);
                
                
                
                UnitData tempData=new UnitData();//为了阅读或以后维护,与前一个if重复
                tempData.isFree=false;
                tempData.panel=panel;
                tempData.name=name;     
                tempData.parent=splitPanel;
                splitPanel.setRightComponent(panel);
                componentMap.put(name, tempData);                
            }
            
        }
        return true;
    }
    
    /**
     * 获得指定名称的JPanel.注意:仅返回JPanel。
     * @param name ----分割区域名。在add方法中,通过name参数进行定义。<br>
     * 初始(即构造方法中)仅有一个名为root的区域。
     */
    public JPanel get(String name){
        UnitData data=componentMap.get(name);
        if (data!=null){
            return data.panel;
        } else {
           return null;
        }
      
    }
    
    /**
     * 获得所有分割名称
     */
    public List getSplitName(){
        List<String> l=new ArrayList();        
        for (String t :componentMap.keySet()){
            l.add(t);
        }
        return l;
    }
    //<editor-fold defaultstate="collapsed" desc="测试"> 
    public static  void createPanel() {
        JFrame f = new JFrame("d");   
        f.setSize(400, 300);
        JPanel p = (JPanel) f.getContentPane(); 
        
        
        FSplitPanel pss=new FSplitPanel();
        p.add( pss); 
         
        JPanel t=new JPanel(); 
        pss.add("root", "left", t, FSplitPanel.VERTICAL_SPLIT);
        
        t=new JPanel(new FlowLayout(FlowLayout.LEFT));
        t.add(new JLabel("right"));
        pss.add("left", "right", t, FSplitPanel.VERTICAL_SPLIT);
        
        t=new JPanel(new FlowLayout(FlowLayout.LEFT));
        t.add(new JLabel("left1"));
        pss.add("left", "left1", t, FSplitPanel.VERTICAL_SPLIT);
        
        t=new JPanel(new FlowLayout(FlowLayout.LEFT));       
        t.add(new JLabel("left11"));
        pss.add("left", "left11", t, FSplitPanel.HORIZONTAL_SPLIT);
        
        t=new JPanel(new FlowLayout(FlowLayout.LEFT));
        t.add(new JLabel("right1"));
        pss.add("right", "right1", t, FSplitPanel.VERTICAL_SPLIT);
        
        t=new JPanel(new FlowLayout(FlowLayout.LEFT));         
        t.add(new JLabel("leftddd"));
        pss.add("right1", "leftddd", t, FSplitPanel.VERTICAL_SPLIT);
        
        t=new JPanel(new FlowLayout(FlowLayout.LEFT));
        t.add(new JLabel("right11"));
        pss.add("right1", "right11", t, FSplitPanel.VERTICAL_SPLIT);
       
        t=pss.get("left");
        t.setBackground(Color.blue);
        
        t=pss.get("right1");
        t.setBackground(Color.red);
        
        t=pss.get("right11");
        t.setBackground(Color.yellow);
        
        t=pss.get("left11");
        t.setBackground(Color.pink);
                
        f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        f.setLocationRelativeTo (null);
        f.setVisible (true);
    }
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {    
                createPanel();
            }
        });
    } 
    //</editor-fold>
    
    
}
  • 大小: 26.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics