`
yunhaifeiwu
  • 浏览: 163032 次
  • 性别: 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
分享到:
评论

相关推荐

    labview数组的使用

    在LabVIEW中,数组是一种基础且重要的数据结构,它允许用户存储和操作同一类型的数据集合。本篇文章将深入探讨LabVIEW中的数组及其使用方法。 一、数组的基本概念 1. 一维数组:一维数组类似于线性列表,包含相同...

    拼图游戏(java实现)

    3. **数据结构与算法**:游戏逻辑可能涉及到数组或链表等数据结构来存储拼图块的位置和状态。解决拼图问题可能需要运用回溯算法或贪心策略,通过检查相邻块是否能正确匹配来逐步还原图片。 4. **状态管理**:游戏会...

    java做的拼图

    拼图游戏是一种广受欢迎的智力挑战游戏,通常涉及到将一个分割成若干块的图像重新组合起来。在这个特定的项目中,我们看到的是使用Java编程语言来实现的一个单线程版本的拼图游戏。下面我们将详细讨论Java在实现拼图...

    易语言多宫格自定义拼图游戏源码

    2. 数据结构与算法:为了实现拼图的移动和复原,开发者可能采用了数据结构(如数组或链表)来存储拼图的各个部分,并设计了相应的算法(如旋转、交换相邻块等)来处理用户的操作。 3. 事件驱动编程:易语言支持事件...

    拼图游戏源码

    6. **数据结构**:为了有效地存储和操作拼图碎片,源码可能会使用数组、链表或者其他数据结构。例如,每个碎片可以表示为一个对象,包含其位置和图像信息。 7. **错误处理**:良好的代码应该能够处理可能出现的异常...

    自己写的华容道游戏,java源码

    棋盘可以由二维数组或者链表等数据结构表示,每个元素对应棋盘上的一个位置。此外,还需设计一个`Board`类来管理棋盘的状态,包括初始设置、合法性检查以及移动操作。 碰撞处理是游戏中的关键部分。在Java中,可以...

    拼图游戏vb

    5. 数据结构:为了高效地存储和操作拼图碎片,可能需要使用数组或者自定义的数据结构,如链表或队列。 6. 用户交互:良好的用户体验是游戏成功的关键,可能需要添加音效、动画效果、提示信息等功能,提升游戏的趣味...

    java编写的拼图游戏

    6. **数据结构**:为了有效地存储和操作拼图,可能会用到数组、链表或队列等数据结构。例如,用二维数组表示游戏面板,其中每个元素对应一个拼图块,而队列则可能用于实现搜索算法。 7. **错误处理**:良好的错误...

    java做的拼图游戏

    4. **数据结构**:为了存储拼图的状态,我们可以使用数组或链表等数据结构。例如,每个拼图小块可以表示为一个类,包含位置、方向等信息。 5. **算法设计**:拼图游戏的核心在于如何判断两个小块能否相邻以及如何...

    Java写的拼图游戏.zip

    此外,对于拼图游戏,可能会使用数据结构,如数组或链表来存储和操作图像碎片,算法如深度优先搜索(DFS)或广度优先搜索(BFS)来解决拼图问题。 1. **JavaFX或Swing**:这两个是Java提供的图形用户界面(GUI)...

    易语言简易拼图游戏源码.zip易语言项目例子源码下载

    4. **数据结构与算法**:为了存储和管理拼图的状态,可能需要用到数组、链表等数据结构。同时,解决拼图游戏的逻辑可能需要实现回溯算法或者贪心算法。 5. **文件操作**:源码中可能包含读取和保存游戏进度的功能,...

    Java的拼图游戏~~~~~~~~~~~

    游戏的核心是图像,因此需要对图像进行读取、分割和重新组合。Java的`java.awt.image`包提供了`BufferedImage`类用于处理图像。你可以先加载一个完整的图像,然后使用`getSubimage()`方法将其切割成多个部分。 3. ...

    java 拼图游戏代码

    3. **数据结构与算法**:为了存储和操作拼图的状态,可能需要使用数组或链表等数据结构。游戏的解决算法可能涉及到深度优先搜索(DFS)、广度优先搜索(BFS)或A*搜索等路径查找算法。 4. **事件监听**:通过实现`...

    netbeans拼图游戏

    5. **数据结构**:为了存储和操作拼图的状态,我们可以使用二维数组或者链表来表示9个小块的位置。每次移动或旋转块时,都需要更新这个数据结构。 6. **算法实现**:拼图游戏的解决策略可能涉及深度优先搜索、回溯...

    自己做的拼图

    在实现拼图游戏中,开发者可能使用了Java的Swing或JavaFX库来构建图形用户界面,以及可能使用了数据结构(如数组或链表)和算法(如排序或搜索)来处理和操作拼图的各个部分。 在【压缩包子文件的文件名称列表】中...

    JAVA拼图游戏源代码

    5. **数据结构**:数组、链表或栈可能被用于存储和操作拼图块的位置和状态。理解这些数据结构及其操作是理解代码的关键。 6. **事件驱动编程**:当用户点击按钮或拖动拼图块时,程序会响应这些事件并执行相应的动作...

    Java 拼图 自由拖动拼图片 随机形状

    可能使用了分治法或者矩阵操作来处理图像切割,同时可能还需要一种有效的数据结构(如链表或数组)来存储和操作拼图块的位置信息。 总的来说,这个Java拼图应用融合了图像处理、GUI设计、事件驱动编程、音频播放和...

    坦克大战Java小游戏程序源代码,j2se

    7. **数据结构与算法**:地图和障碍物的生成可能涉及到数据结构,如数组、链表或者更复杂的图结构。同时,快速的碰撞检测可能需要用到特定的算法,如四叉树或空间分割算法。 8. **状态机设计**:游戏有多种状态,如...

    2021-2022计算机二级等级考试试题及答案No.13361.docx

    - **知识点解释**:链表是一种常见的数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。 - **应用场景**:动态数据存储。 - **相关知识点**:链表的存储位置不一定是连续的。 #### 17. 计算机...

Global site tag (gtag.js) - Google Analytics