<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    java something

    不要以為......很遙遠
    隨筆 - 23, 文章 - 1, 評論 - 2, 引用 - 0
    數(shù)據(jù)加載中……

    Jree

    樹控件很適合用來顯示,導(dǎo)航和編輯結(jié)構(gòu)化對象;但是JTree很復(fù)雜,swing中有整個一個包都是針對它的(javax.swing.tree),注意樹控件是顯示的,但是樹數(shù)據(jù)結(jié)構(gòu)是一種集合接口的實現(xiàn),就如同JList和java.util.List一樣,他們應(yīng)用在不同層,當(dāng)然你使用Jlist來顯示List接口的實現(xiàn)者那是很般配的。
    *
    **
    關(guān)于樹的術(shù)語如根,節(jié)點,葉子,深度,路徑,平衡性,邊,子樹;不需要我這里過多的解釋,任何一本數(shù)據(jù)結(jié)構(gòu)的書籍都會介紹他們。我這里主要是講述樹控件。

    樹遍歷這個概念先提一下:遍歷即逐個訪問,對于樹而言主要有三種:前序,后序,中序遍歷樹的每個節(jié)點。遍歷一般是用遞歸算法來實現(xiàn)的,三種遍歷法區(qū)別于先訪問樹的那個部分。樹遍歷也是比較難的一個技術(shù),不好掌握,我在大學(xué)時用匯編實現(xiàn)過這三種算法,到現(xiàn)在還記憶猶新(完全自己找到的規(guī)律),一下來和朋友們分享一下。
    對于一個有兩個子節(jié)點的樹(或多個子節(jié)點),請你沿著樹的外圍畫一個輪廓線:

     

    ———>         >——————
            /             \
          /                 \
         /_____>____\     

           這是大致繞樹行走的輪廓線,大家都知道(或許你還不知道)函數(shù)的調(diào)用時控制流的傳遞就是這個樣子的。(控制流是線程執(zhí)行方法時的形象表述)比如一下函數(shù): main(){

         f1();
         f2();
    }//該函數(shù)的控制流向是:先傳給main,再由main()傳給f1,之后退回到mian(),在傳給f2()在由f2退回給main之后結(jié)束程序。異步方法調(diào)用時才會從這個封閉的輪廓中分出一個分支來。現(xiàn)在來談你如何設(shè)計一個樹遍歷方法:
    我們來看一個函數(shù)的幾個關(guān)鍵部位,
           func(){
            entry入口處
              
                中間部位           

            return出口處   
          }也許你很迷惑這與樹遍歷算法有和關(guān)系,告訴你吧這三個特殊部位就是你在設(shè)計遞歸時,遞歸函數(shù)應(yīng)該出現(xiàn)的位置,他們出現(xiàn)在不同的位置就是不同的“序”,偽碼如:
    先序遍歷
    traversTree(Node root){
       if(root !=null){
         if(root.isLeaf()){//當(dāng)是葉子時,
             visit(root);//前序遍歷是先遍歷頁節(jié)點
         }   
             Node[] children=root.getChildren();//獲取所有子樹
             for(Node n:children){
               traversTree(n);//遞歸遍歷所有子樹,注意子樹可能為空。
              }
       }

    }

    中序遍歷(亦稱廣度優(yōu)先遍歷,總是先遍歷樹的根)

    traversTree(Node root){
       if(root !=null){
         //樹非空
         visit(root); //這是中序遍歷 visit出現(xiàn)與遞歸函數(shù)之前。
        
         Node[] children=root.getChildren();//獲取所有子樹
             for(Node n:children){
               traversTree(n);//遞歸遍歷所有子樹,注意子樹可能為空。
              }
       }

    }

    后序遍歷(亦稱深度優(yōu)先搜索):
    traversTree(Node root){
       if(root !=null){
            
         Node[] children=root.getChildren();//獲取所有子樹
             for(Node n:children){
               traversTree(n);//遞歸遍歷所有子樹,注意子樹可能為空。
              }
        
         
         visit(root); //這是后序遍歷 visit出現(xiàn)在遞歸函數(shù)之后。
       }

    }

    以上三個算法,可能有點不正確,我沒測試過,時間太久了有點忘了,總之為大家做個參考吧!
    因為樹結(jié)構(gòu)典型的是應(yīng)用了組合設(shè)計模式,所以只要涉及到樹肯定涉及遍歷,和遞歸。所以這里羅嗦一下。   所有的樹都是節(jié)點                   
    **
    ***
    swing中Jtree處理樹結(jié)構(gòu)是通過樹模型接口,它實現(xiàn)了TreeNode接口(在api文檔中竟看不到此信息!),DefaultMutableTreeNode類實現(xiàn)了TreeNode接口,并提供了前,中,后序的樹遍歷能力。
    JTree圖形化的顯示了樹結(jié)構(gòu)的每一個節(jié)點,所有的UI控件都有兩個目的,顯示和輸入(輸入包括數(shù)據(jù)的輸入如JTextField和命令輸入如菜單,按鈕等),JTree既可以用于樹結(jié)構(gòu)的顯示,也可以用于命令的輸入,或使得我們編輯樹節(jié)點。
    樹節(jié)點可以被選中,它由TreeSelectionModel來控制,選擇涉及到維護作為TreeNode實例的樹節(jié)點間的路徑軌跡。樹控件典型的可以激發(fā)兩類事件:TreeModelEvent和TreeExpansionEvent,當(dāng)然其他Awt和Swing事件也可由樹控件激發(fā)(看其繼承層次結(jié)構(gòu)即可知)比如MouseListener可用來截取鼠標事件。JTree擴展了Scrollable接口,可被放在一個滾動面板中。

    JTree的構(gòu)造:可使用默認的構(gòu)造方法,提供一個TreeNode作為其根節(jié)點,提供一個TreeModel包含所有其它的節(jié)點,或提供一個一維數(shù)組,向量,或?qū)ο蟮墓1恚瑢τ谶@些集合中的單個元素,如果它又是一個集合,那么他們會被解釋顯示為子樹,該功能由JTree的內(nèi)部類DynamicUtilTreeNode完成。
    ***
    ****
    TreeModel接口:
    該接口的實現(xiàn)者為JTree提供顯示的數(shù)據(jù),如果你熟悉MVC模式,你應(yīng)該明白所有的swing或awt控件中模型的作用就是為相應(yīng)的控件提供數(shù)據(jù)。當(dāng)模型的數(shù)據(jù)結(jié)構(gòu)有所變化時它會通知視圖(這里就是JTree)來更新顯示。當(dāng)然模型也可以添加其他的監(jiān)聽器如Jtree的addTreeModelListener,你可以實現(xiàn)該監(jiān)聽器,來使你自己的類接收模型變化給你的通知。如果你不熟悉MVC模式,請參考POSA卷一或其他資料,順便提一下在我們學(xué)校GUI時都知道有MVC模式的應(yīng)用,往往不知道那個Controller是什么類,其實就是視圖的監(jiān)聽器,比如ActionListener,注意別被眾多的監(jiān)聽器弄昏了,一類是模型需要添加的,一類是視圖(比如JComponent的子類)需要添加的。控制的流向或數(shù)據(jù)的流向是相反的,視圖需要添加的監(jiān)聽器(我們常常實現(xiàn)他們)才是控制器。

    因為模型和視圖都能夠觸發(fā)事件,比如視圖(JTree等控件)是觸發(fā)用戶輸入導(dǎo)致的事件,而模型觸發(fā)的事件是因為模型中維護的數(shù)據(jù)有所變動才觸發(fā)的(比如,樹模型中樹節(jié)點的增刪,改,或樹路徑的變動)。而他們都使用了觀察者模式,算了不多說了,到時全弄成模式了,會搞昏大家的。繼續(xù)....

    JTree的setModel和getModel方法是用來更換/設(shè)置和獲取模型的方法。你可替換現(xiàn)有JTree的模型,或者你想這樣用,兩個模型,一個用,一個備。如果構(gòu)造模型復(fù)雜耗時的話,先在后臺構(gòu)造好一個在換掉原先的。就如同雙緩沖技術(shù)的思路那樣。
    ****
    *****
    雜項:
    DefultTreeModel是對TreeModel接口的默認實現(xiàn)類,
    TreeNode接口可告訴你改實現(xiàn)者是否為一個葉子,一個父節(jié)點等。MutalbeTreeNode接口擴展了TreeNode接口,我們可在該實現(xiàn)者中存放一個我們自己的類實例(setUserObject()/getUserObject);
    defaultMutableTreeNode 實現(xiàn)了MutableTreeNode接口,children()方法返回以一維向量形式存放的直接子節(jié)點的枚舉,也可以使用getChildAt()返回特定索引位置的子節(jié)點(注意子節(jié)點完全可以是一顆子樹)該類提供了前中后序訪問樹的能力:preorderEnumeration(),,breadthFirstEnumeration(),depthFirstEnumeration()postorderEnumeration()最后兩個方法同行為,只不過是不同的稱號而已。

    TreePath:該類用一系列節(jié)點表示一個從樹根到一個節(jié)點的路徑,它是只讀的,提供與其他路徑比較的能力。
    TreeCellRenderrer接口:渲染tree的一個單元的組件,我們自己實現(xiàn)該接口并用jtree的setCellRenderer()方法替換原先的渲染器,可以是樹節(jié)點在選中,獲取焦點,不同的樹狀態(tài)(葉子或父節(jié)點,展開,或收縮)等不同的狀態(tài)下的外觀。
    DefaultTreeCellRenderer類是TreeCellRenderrer接口的默認實現(xiàn),它擴展了JLabel,并基于以上描述的樹狀態(tài)來渲染樹節(jié)點,其提供的屬性包括圖標,背景色,前景色等,其get和set方法是我們可以訪問的,通過這些方法你當(dāng)然可以換掉樹節(jié)點的圖標了。

    CellEditor接口:定義了控制何時編輯將開始,結(jié)束,提取一個新的結(jié)果,是否編輯請求改變當(dāng)前組件的選擇,請參考API文檔看該接口的方法。該接口在JTree和JTable中都有用到。,該接口也可以添加監(jiān)聽器,當(dāng)編輯停止或取消時會激發(fā)ChangeEvents到其所有的注冊處理器哪里。
    TreeCellEditor接口擴展了CellEditor接口,jtree的setCellEditor()使得我們可以用任何一個可充當(dāng)編輯器的組件替換掉原來的那個。DefaultCellEditor實現(xiàn)了該接口,這個編輯器允許使用JTextField,JComboBox或是JCheckBox組件來編輯數(shù)據(jù),其保護的內(nèi)部類EditorDelegate會響應(yīng)getCellEditorValue()方法把當(dāng)前值返回。DefaultCellEditor僅基于以上三個J控件作為編輯器,其clickCountToStart方法決定鼠標單擊幾次會觸發(fā)編輯。默認對于JTextField是兩次,JComboBox和JCheckBox是一次,changeEvents會在stopCellEditing()和cancelCellEditing()時激發(fā)。
    DefaultTreeCellEditor擴展了DefaultCellEditor類并且是TreeCellEditor的默認實現(xiàn)類,他使用JTextField來編輯節(jié)點數(shù)據(jù),在鍵入ENTER鍵后stopCellEditing()會被調(diào)用。對于樹節(jié)點的編輯我們可添加自己的時間監(jiān)聽器來處理他們。默認時編輯開始于節(jié)點被單擊三次或兩次(時間間隔在內(nèi)部會用一個定時器來決定),也可以改變他們的數(shù)目setClickCountToStart();
    JTree的選擇是基于行和樹路徑的,我們可以選擇使用那個。

    TreeSelectionModel接口用于樹選擇模型,支持三種選擇,SINGLE_TREE_SELECTION,
    DISCONTIGUOUS_TREE_SELECTION,CONTIGUOUS_TREE_SELECTION,set/getSelectionMode()可以訪選擇模型。getSelectionPath『s』()會返回一個當(dāng)前選中的樹路徑。DefaultTreeSelectionModel默認實現(xiàn)了該接口,該類提供TreeSelectionlistener通知,當(dāng)樹路徑選擇發(fā)生變化時。

    TreeModelListener實現(xiàn)者可以偵聽模型變化,TreeSelectionListener用來偵聽視圖JTree的selection(僅有一個方法valueChanged(TreeSlectcionEvent tsEvt));
    TreeExpansionListener用來對樹展開收縮進行處理。
    TreeW illExpandListener在樹“將要”展開和收縮時得到通知,你可截獲處理,ExpandVetoException異常如果拋出,那么樹不會展開和收縮。

    TreeModelEvent,用來通知模型的監(jiān)聽器,JTree的數(shù)據(jù)部分或全部發(fā)生了變化。該事件對象封裝了源組件的引用,封裝了一個TreePath或一個用來表示路徑的數(shù)組。
    TreeselectionEvent,視圖會用其通知所有視圖監(jiān)聽器TreeSelectionListeners,選擇發(fā)生了變化。
    TreeExpansionEvent,用來封裝相應(yīng)最近或可能展開或收縮的TreePath,使用getPath()方法訪問樹路徑。
    ExpandVetoException異常可由TreeWillExpandListener拋出,來否決樹路徑的展開和收縮。

    JTree提供的現(xiàn)成方便的UI屬性:
    myJTree.putClientProperty("JTree.lineStyle", "Angled");//更改線型。
    如同其他Swing組件,我們也可以改變默認的用于JTree的UI資源(全局性的):
    UIManager.put("Tree.hash",
    new ColorUIResource(Color.lightGray));//改變渲染節(jié)點間edges邊的顏色。
    UIManager.put("Tree.openIcon", new IconUIResource(
    new ImageIcon("myOpenIcon.gif")));//改變一個打開的樹節(jié)點的圖標。同理可用于其它情況:Tree.leafIcon, Tree.expandedIcon,和Tree.closedIcon, Tree.collapsedIcon。

    其他控制TreeUI顯示的方法:
    myTree.setRowHeight()//控制樹節(jié)點的行高,
    JTree的UI委托也提供了更改樹外觀的方法(相比于UIManager的方法,這里是局部的)。
    BasicTreeUI basicTreeUI = (BasicTreeUI) myJTree.getUI();
    basicTreeUI.setRightChildIndent(10);
    basicTreeUI.setLeftChildIndent(8);


    以上簡要提及了JTree的方方面面,許多的事件,將聽器模型,請仔細分析,一定要分清哪些是針對模型的那些是針對視圖的。

    *****
    ******
    簡單的示例,我這里僅用到了最簡單的樹構(gòu)造方法,和一個監(jiān)聽器,在
    以后我的自學(xué)過程中,我會繼續(xù)試用其他的JTree知識,我的JTree學(xué)習(xí)
    最終都是想實現(xiàn)那個GUI上的授權(quán)控制系統(tǒng),請參考其他篇章,
    至于這里用到的LAndFSysMenu類,在我的其他篇章中有該類的實現(xiàn)。
    package jTreeDemo;

    import java.awt.Container;
    import javax.swing.*;
    import javax.swing.event.TreeSelectionEvent;
    import javax.swing.event.TreeSelectionListener;
    import lookAndFeelSys.*;
    import userInterfaces.UIUtil;
    import java.awt.*;
    import java.util.Hashtable;
    import java.util.Vector;
    import javax.swing.tree.*;


    public class JTreeTest extends JFrame{

    public static void main(String[] args){
    new JTreeTest("測試");
    }

    public JTreeTest(String title){
       super(title);
       biuldFrame();
    }

       private void biuldFrame(){
        JMenuBar jmb=new JMenuBar();
       
        JMenu jm=new LAndFSysMenu();
        //JMenu jm=new JMenu("hello");
       
        jmb.add(jm);
        this.setJMenuBar(jmb);
       
        buildFrmContent();   
       
        UIUtil.SetComponentDimension(this,0.5,0.6);
        UIUtil.SetComponentToCenterOfScreen(this);
        this.setVisible(true);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
       }
      
       private void buildFrmContent(){
        Container root_c=this.getContentPane();
        JTabbedPane jtp=new JTabbedPane();
        Container c = new JPanel();
        jtp.addTab("靜態(tài)樹組件練習(xí)",c );
        jtp.addTab("事件監(jiān)聽",this.treeDemo2());
         

       root_c.add(jtp);

    c.setLayout(new GridLayout(2,4));
    JScrollPane jsp_1=new JScrollPane();
    JScrollPane jsp_2=new JScrollPane();
    JScrollPane jsp_3=new JScrollPane();
    JScrollPane jsp_4=new JScrollPane();


    /*為JTree準備顯示的模型*/
    Object[] m1=new String[]{"節(jié)點1","節(jié)點2","節(jié)點3"};
    Object[] m2=new String[][]{
        {"1.1","1.2","1.3"},
        {"2.1","2.2","2.3"},
        {"3.1","3.2","3.3"}
    };
    Vector<Object> m3=new Vector<Object>();
    m3.add("1");
    m3.add("2");
    m3.add(m1);
    m3.add(m2);
    Hashtable<String,Object> m4=new Hashtable<String,Object>();
    m4.put("子一","葉子");
    m4.put("子二", m1);
    m4.put("子三",m3);


    JTree jtr_1=new JTree(m1);
    jsp_1.getViewport().add(jtr_1);
    JTree jtr_2=new JTree(m2);
    jsp_2.getViewport().add(jtr_2);
    JTree jtr_3=new JTree(m3);
    jsp_3.getViewport().add(jtr_3);
    JTree jtr_4=new JTree(m4);
    jsp_4.getViewport().add(jtr_4);


    c.add(jsp_1);
    c.add(jsp_2);
    c.add(jsp_3);
    c.add(jsp_4);

    /*jsp_1.getViewport().add(jtr_1);
    c.add(jsp_1);*/
       }

       /*<<     另一組JTree實例:*/
       private JPanel treeDemo2(){
        JPanel rsltPanel=new JPanel();
        rsltPanel.setLayout(new BorderLayout());
       
        JLabel jl_msg=new JLabel("此標簽用來顯示樹選擇情況");
        JScrollPane jsp_1=new JScrollPane();
        Object[] m=new String[]{"節(jié)點1","節(jié)點2","節(jié)點3"};
        JTree jtr=new JTree(m);
        jtr.getSelectionModel()
        .addTreeSelectionListener(new MySelectionLstnr(
          jl_msg));
       
        jsp_1.getViewport().add(jtr);
       
        rsltPanel.add(jsp_1,BorderLayout.CENTER);
        rsltPanel.add(jl_msg,BorderLayout.SOUTH);
        return rsltPanel;
       }
       class MySelectionLstnr implements TreeSelectionListener{
        //該內(nèi)部類實現(xiàn)樹監(jiān)聽器,在樹被選中后將選中的節(jié)點
        //信息打印到一個Label上
        private JLabel jl_msg=null;
       
        public MySelectionLstnr(JLabel msgLabel){
        this.jl_msg=msgLabel;
        }
    @Override
    public void valueChanged(TreeSelectionEvent e) {
       // 凡是樹選擇的處理都涉及到樹路徑的處理:
       TreePath path = e.getPath();
       Object[] nodes = path.getPath();
      
       //當(dāng)前選中的節(jié)點是樹路徑上最后一個節(jié)點
         Object selectedNode=nodes[nodes.length-1 ];
         if(this.jl_msg!=null){
         this.jl_msg.setText("選中的節(jié)點上的文本是:"+
             selectedNode.toString());
         }
    }


       }
       /*另一組JTree實例:>>*/
    }

     

    ******
    參考Java Swing (Manning出版社)swing hack (orelly出版社)。

    posted on 2011-03-23 09:09 Jamie 閱讀(2214) 評論(0)  編輯  收藏 所屬分類: swing

    主站蜘蛛池模板: 91亚洲国产成人久久精品网站| 中文字幕在线免费| 亚洲色在线无码国产精品不卡| 亚洲综合国产精品第一页| 国产亚洲一区二区在线观看| 18禁成年无码免费网站无遮挡| 国产一级淫片a免费播放口| 免费无码又爽又黄又刺激网站| 亚洲av无码国产综合专区| 亚洲国产精品无码AAA片| 亚洲片国产一区一级在线观看| 免费羞羞视频网站| 精品一区二区三区无码免费直播| 亚洲国产成人在线视频| 亚洲精品人成在线观看| 亚洲日韩国产精品第一页一区 | 亚洲网站视频在线观看| 亚洲av一综合av一区| 国产亚洲日韩一区二区三区| 亚洲国产综合精品一区在线播放| 四虎成人免费网址在线| 四虎成人免费大片在线| 成年女人免费视频播放体验区 | 亚洲人成网站日本片| 麻豆亚洲AV永久无码精品久久| 久久久久亚洲AV成人无码| 亚洲色大成网站www永久一区| 亚洲视频在线一区二区| 亚洲国产中文字幕在线观看| www.91亚洲| 久久乐国产精品亚洲综合| 国产精品永久免费10000| 4444www免费看| 免费黄色网址网站| 美女网站免费福利视频| 成年大片免费视频| 日韩电影免费在线观看视频| 国产在线观看免费完整版中文版| 亚洲av无码乱码在线观看野外| 日本中文一区二区三区亚洲| 亚洲国产精品嫩草影院久久 |