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

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

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

    java something

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

    2011年3月23日

    Activity生命周期

    現(xiàn)有兩個(gè)Activity:  Activity1,Activity2

    先啟動(dòng)Activity1運(yùn)行順序?yàn)椋?Activity1 onCreate -> Activity1 onStart -> Activity1 onResume
    用Intent從Activity1跳到Activity2運(yùn)行順序 : 
    Activity1 onPause -> Activity2 onCreate -> Activity2 onStart -> Activity2 onResume ->Activity1 onStop -> Activity1  onDestroy
    退出應(yīng)用程序: Activity2 onResume ->Activity2 onStop -> Activity2  onDestroy

    posted @ 2011-09-02 17:48 Jamie 閱讀(222) | 評(píng)論 (0)編輯 收藏

    控制3個(gè)線程運(yùn)行順序的Demo

    本程序可以控制3個(gè)線程按順序執(zhí)行, 代碼如下:

    public class Test3 {

     public static void main(String[] args) throws IOException {
      final Test obj = new Test();
      
      new Thread()
      {
       public void run()
       {
        obj.m1();
       }
      }.start();
      new Thread()
      {
       public void run()
       {
        obj.m2();
       }
      }.start();
      new Thread()
      {
       public void run()
       {
        obj.m3();
       }
      }.start();
      
     }

    }

    class Test
    {
     static int count;
     volatile int target = 1;
     synchronized void m1()
     { 
       for (int i = 0; i < 10; i++)
       {
        while (target == 2 || target == 3)
        {
         try {
          wait();
         } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
         }
        }
        System.out.println("m1() =" + i);
        target = 2;
        notifyAll();
       }
     }
     
     synchronized void m2()
     {
      for (int i = 0; i < 10; i++)
      {
       while (target == 1 || target == 3)
       {
        try {
         wait();
        } catch (InterruptedException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
        }
       }
       System.out.println("m2() =" + i);
       target = 3;
       notifyAll();
      }
     }
     
     synchronized void m3()
     {
      for (int i = 0; i < 10; i++)
      {
       while (target == 1 || target == 2)
       {
        try {
         wait();
        } catch (InterruptedException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
        }
       }
       System.out.println("m3() =" + i);
       target = 1;
       notifyAll();
      }
     }
    }

    posted @ 2011-09-02 02:27 Jamie 閱讀(1769) | 評(píng)論 (2)編輯 收藏

    線程的同步與共享

         摘要: 線程的同步與共享 前面程序中的線程都是獨(dú)立的、異步執(zhí)行的線程。但在很多情況下,多個(gè)線程需要共享數(shù)據(jù)資源,這就涉及到線程的同步與資源共享的問題。 1 資源沖突 下面的例子說明,多個(gè)線程共享資源,如果不加以控制可能會(huì)產(chǎn)生沖突。 程序CounterTest.java   Code highlighting produced by Actipro CodeHighlight...  閱讀全文

    posted @ 2011-09-02 01:38 Jamie 閱讀(477) | 評(píng)論 (0)編輯 收藏

    線程的狀態(tài)與調(diào)度

      1,線程的生命周期

            線程從創(chuàng)建、運(yùn)行到結(jié)束總是處于下面五個(gè)狀態(tài)之一:新建狀態(tài)、就緒狀態(tài)、運(yùn)行狀態(tài)、阻塞狀態(tài)及死亡狀態(tài)。



        1.新建狀態(tài)(New): 
            當(dāng)用new操作符創(chuàng)建一個(gè)線程時(shí), 例如new Thread(r),線程還沒有開始運(yùn)行,此時(shí)線程處在新建狀態(tài)。 當(dāng)一個(gè)線程處于新生狀態(tài)時(shí),程序還沒有開始運(yùn)行線程中的代碼

         2.就緒狀態(tài)(Runnable)

            一個(gè)新創(chuàng)建的線程并不自動(dòng)開始運(yùn)行,要執(zhí)行線程,必須調(diào)用線程的start()方法。當(dāng)線程對(duì)象調(diào)用start()方法即啟動(dòng)了線程,start()方法創(chuàng)建線程運(yùn)行的系統(tǒng)資源,并調(diào)度線程運(yùn)行run()方法。當(dāng)start()方法返回后,線程就處于就緒狀態(tài)。

            處于就緒狀態(tài)的線程并不一定立即運(yùn)行run()方法,線程還必須同其他線程競爭CPU時(shí)間,只有獲得CPU時(shí)間才可以運(yùn)行線程。因?yàn)樵趩?/span>CPU的計(jì)算機(jī)系統(tǒng)中,不可能同時(shí)運(yùn)行多個(gè)線程,一個(gè)時(shí)刻僅有一個(gè)線程處于運(yùn)行狀態(tài)。因此此時(shí)可能有多個(gè)線程處于就緒狀態(tài)。對(duì)多個(gè)處于就緒狀態(tài)的線程是由Java運(yùn)行時(shí)系統(tǒng)的線程調(diào)度程序(thread scheduler)來調(diào)度的。

        3.運(yùn)行狀態(tài)(Running)

            當(dāng)線程獲得CPU時(shí)間后,它才進(jìn)入運(yùn)行狀態(tài),真正開始執(zhí)行run()方法.

        
    4. 阻塞狀態(tài)(Blocked)

            線程運(yùn)行過程中,可能由于各種原因進(jìn)入阻塞狀態(tài):
            1>線程通過調(diào)用sleep方法進(jìn)入睡眠狀態(tài);
            2>線程調(diào)用一個(gè)在I/O上被阻塞的操作,即該操作在輸入輸出操作完成之前不會(huì)返回到它的調(diào)用者;
            3>線程試圖得到一個(gè)鎖,而該鎖正被其他線程持有;
            4>線程在等待某個(gè)觸發(fā)條件;
            ......           

            所謂阻塞狀態(tài)是正在運(yùn)行的線程沒有運(yùn)行結(jié)束,暫時(shí)讓出
    CPU,這時(shí)其他處于就緒狀態(tài)的線程就可以獲得CPU時(shí)間,進(jìn)入運(yùn)行狀態(tài)。

        5. 死亡狀態(tài)(Dead)

            有兩個(gè)原因會(huì)導(dǎo)致線程死亡:
            1) run方法正常退出而自然死亡,
            2) 一個(gè)未捕獲的異常終止了run方法而使線程猝死。
            為了確定線程在當(dāng)前是否存活著(就是要么是可運(yùn)行的,要么是被阻塞了),需要使用isAlive方法。如果是可運(yùn)行或被阻塞,這個(gè)方法返回true; 如果線程仍舊是new狀態(tài)且不是可運(yùn)行的, 或者線程死亡了,則返回false.




    2,  線程的優(yōu)先級(jí)和調(diào)度

    Java的每個(gè)線程都有一個(gè)優(yōu)先級(jí),當(dāng)有多個(gè)線程處于就緒狀態(tài)時(shí),線程調(diào)度程序根據(jù)線程的優(yōu)先級(jí)調(diào)度線程運(yùn)行。

    可以用下面方法設(shè)置和返回線程的優(yōu)先級(jí)。

        · public final void setPriority(int newPriority) 設(shè)置線程的優(yōu)先級(jí)。

        · public final int getPriority() 返回線程的優(yōu)先級(jí)。

    newPriority為線程的優(yōu)先級(jí),其取值為110之間的整數(shù),也可以使用Thread類定義的常量來設(shè)置線程的優(yōu)先級(jí),這些常量分別為:Thread.MIN_PRIORITYThread.NORM_PRIORITYThread.MAX_PRIORITY,它們分別對(duì)應(yīng)于線程優(yōu)先級(jí)的1510,數(shù)值越大優(yōu)先級(jí)越高。當(dāng)創(chuàng)建Java線程時(shí),如果沒有指定它的優(yōu)先級(jí),則它從創(chuàng)建該線程那里繼承優(yōu)先級(jí)。

    一般來說,只有在當(dāng)前線程停止或由于某種原因被阻塞,較低優(yōu)先級(jí)的線程才有機(jī)會(huì)運(yùn)行。

    前面說過多個(gè)線程可并發(fā)運(yùn)行,然而實(shí)際上并不總是這樣。由于很多計(jì)算機(jī)都是單CPU的,所以一個(gè)時(shí)刻只能有一個(gè)線程運(yùn)行,多個(gè)線程的并發(fā)運(yùn)行只是幻覺。在單CPU機(jī)器上多個(gè)線程的執(zhí)行是按照某種順序執(zhí)行的,這稱為線程的調(diào)度(scheduling)

    大多數(shù)計(jì)算機(jī)僅有一個(gè)CPU,所以線程必須與其他線程共享CPU。多個(gè)線程在單個(gè)CPU是按照某種順序執(zhí)行的。實(shí)際的調(diào)度策略隨系統(tǒng)的不同而不同,通常線程調(diào)度可以采用兩種策略調(diào)度處于就緒狀態(tài)的線程。

    (1) 搶占式調(diào)度策略

         Java運(yùn)行時(shí)系統(tǒng)的線程調(diào)度算法是搶占式的 (preemptive)Java運(yùn)行時(shí)系統(tǒng)支持一種簡單的固定優(yōu)先級(jí)的調(diào)度算法。如果一個(gè)優(yōu)先級(jí)比其他任何處于可運(yùn)行狀態(tài)的線程都高的線程進(jìn)入就緒狀態(tài),那么運(yùn)行時(shí)系統(tǒng)就會(huì)選擇該線程運(yùn)行。新的優(yōu)先級(jí)較高的線程搶占(preempt)了其他線程。但是Java運(yùn)行時(shí)系統(tǒng)并不搶占同優(yōu)先級(jí)的線程。換句話說,Java運(yùn)行時(shí)系統(tǒng)不是分時(shí)的(time-slice)。然而,基于Java Thread類的實(shí)現(xiàn)系統(tǒng)可能是支持分時(shí)的,因此編寫代碼時(shí)不要依賴分時(shí)。當(dāng)系統(tǒng)中的處于就緒狀態(tài)的線程都具有相同優(yōu)先級(jí)時(shí),線程調(diào)度程序采用一種簡單的、非搶占式的輪轉(zhuǎn)的調(diào)度順序。

    (2) 時(shí)間片輪轉(zhuǎn)調(diào)度策略

        有些系統(tǒng)的線程調(diào)度采用時(shí)間片輪轉(zhuǎn)(round-robin)調(diào)度策略。這種調(diào)度策略是從所有處于就緒狀態(tài)的線程中選擇優(yōu)先級(jí)最高的線程分配一定的CPU時(shí)間運(yùn)行。該時(shí)間過后再選擇其他線程運(yùn)行。只有當(dāng)線程運(yùn)行結(jié)束、放棄(yield)CPU或由于某種原因進(jìn)入阻塞狀態(tài),低優(yōu)先級(jí)的線程才有機(jī)會(huì)執(zhí)行。如果有兩個(gè)優(yōu)先級(jí)相同的線程都在等待CPU,則調(diào)度程序以輪轉(zhuǎn)的方式選擇運(yùn)行的線程。

     3.  線程狀態(tài)的改變

    一個(gè)線程在其生命周期中可以從一種狀態(tài)改變到另一種狀態(tài),線程狀態(tài)的變遷如圖所示:

        
        
    1>  控制線程的啟動(dòng)和結(jié)束

    當(dāng)一個(gè)新建的線程調(diào)用它的start()方法后即進(jìn)入就緒狀態(tài),處于就緒狀態(tài)的線程被線程調(diào)度程序選中就可以獲得CPU時(shí)間,進(jìn)入運(yùn)行狀態(tài),該線程就開始運(yùn)行run()方法。

    控制線程的結(jié)束稍微復(fù)雜一點(diǎn)。如果線程的run()方法是一個(gè)確定次數(shù)的循環(huán),則循環(huán)結(jié)束后,線程運(yùn)行就結(jié)束了,線程對(duì)象即進(jìn)入死亡狀態(tài)。如果run()方法是一個(gè)不確定循環(huán),早期的方法是調(diào)用線程對(duì)象的stop()方法,然而由于該方法可能導(dǎo)致線程死鎖,因此從1.1版開始,不推薦使用該方法結(jié)束線程。一般是通過設(shè)置一個(gè)標(biāo)志變量,在程序中改變標(biāo)志變量的值實(shí)現(xiàn)結(jié)束線程。請(qǐng)看下面的例子:

    程序 ThreadStop.java

    import java.util.*;

    class Timer implements Runnable{

        
    boolean flag=true;
        
    public void run(){
          
    while(flag){
            System.out.print(
    "\r\t"+new Date()+"");
            
    try{
                  Thread.sleep(
    1000);
            }
    catch(InterruptedException e){} 
          }
          System.out.println(
    "\n"+Thread.currentThread().getName()+" Stop");
        }

        
    public void stopRun(){
               flag 
    = false;
        }
    }

    public class ThreadStop{
        
    public static void main(String args[]){
           Timer timer 
    = new Timer();
           Thread thread 
    = new Thread(timer);       
           thread.setName(
    "Timer");
           thread.start();

           
    for(int i=0;i<100;i++){
             System.out.print(
    "\r"+i);
            
    try{
                  Thread.sleep(
    100);
            }
    catch(InterruptedException e){} 
           }     
           timer.stopRun();
        }
    }

    該程序在Timer類中定義了一個(gè)布爾變量flag,同時(shí)定義了一個(gè)stopRun()方法,在其中將該變量設(shè)置為false。在主程序中通過調(diào)用該方法,從而改變?cè)撟兞康闹担沟?/span>run()方法的while循環(huán)條件不滿足,從而實(shí)現(xiàn)結(jié)束線程的運(yùn)行。

    說明  Thread類中除了stop()方法被標(biāo)注為不推薦(deprecated) 使用外,suspend()方法和resume()方法也被標(biāo)明不推薦使用,這兩個(gè)方法原來用作線程的掛起和恢復(fù).

    2>  線程阻塞條件

    處于運(yùn)行狀態(tài)的線程除了可以進(jìn)入死亡狀態(tài)外,還可能進(jìn)入就緒狀態(tài)和阻塞狀態(tài)。下面分別討論這兩種情況:

    (1) 運(yùn)行狀態(tài)到就緒狀態(tài)

    處于運(yùn)行狀態(tài)的線程如果調(diào)用了yield()方法,那么它將放棄CPU時(shí)間,使當(dāng)前正在運(yùn)行的線程進(jìn)入就緒狀態(tài)。這時(shí)有幾種可能的情況:如果沒有其他的線程處于就緒狀態(tài)等待運(yùn)行,該線程會(huì)立即繼續(xù)運(yùn)行;如果有等待的線程,此時(shí)線程回到就緒狀態(tài)狀態(tài)與其他線程競爭CPU時(shí)間,當(dāng)有比該線程優(yōu)先級(jí)高的線程時(shí),高優(yōu)先級(jí)的線程進(jìn)入運(yùn)行狀態(tài),當(dāng)沒有比該線程優(yōu)先級(jí)高的線程時(shí),但有同優(yōu)先級(jí)的線程,則由線程調(diào)度程序來決定哪個(gè)線程進(jìn)入運(yùn)行狀態(tài),因此線程調(diào)用yield()方法只能將CPU時(shí)間讓給具有同優(yōu)先級(jí)的或高優(yōu)先級(jí)的線程而不能讓給低優(yōu)先級(jí)的線程。

    一般來說,在調(diào)用線程的yield()方法可以使耗時(shí)的線程暫停執(zhí)行一段時(shí)間,使其他線程有執(zhí)行的機(jī)會(huì)。

    (2) 運(yùn)行狀態(tài)到阻塞狀態(tài)

    有多種原因可使當(dāng)前運(yùn)行的線程進(jìn)入阻塞狀態(tài),進(jìn)入阻塞狀態(tài)的線程當(dāng)相應(yīng)的事件結(jié)束或條件滿足時(shí)進(jìn)入就緒狀態(tài)。使線程進(jìn)入阻塞狀態(tài)可能有多種原因:

    線程調(diào)用了sleep()方法,線程進(jìn)入睡眠狀態(tài),此時(shí)該線程停止執(zhí)行一段時(shí)間。當(dāng)時(shí)間到時(shí)該線程回到就緒狀態(tài),與其他線程競爭CPU時(shí)間。

    Thread類中定義了一個(gè)interrupt()方法。一個(gè)處于睡眠中的線程若調(diào)用了interrupt()方法,該線程立即結(jié)束睡眠進(jìn)入就緒狀態(tài)。

    如果一個(gè)線程的運(yùn)行需要進(jìn)行I/O操作,比如從鍵盤接收數(shù)據(jù),這時(shí)程序可能需要等待用戶的輸入,這時(shí)如果該線程一直占用CPU,其他線程就得不到運(yùn)行。這種情況稱為I/O阻塞。這時(shí)該線程就會(huì)離開運(yùn)行狀態(tài)而進(jìn)入阻塞狀態(tài)。Java語言的所有I/O方法都具有這種行為。

    ③ 有時(shí)要求當(dāng)前線程的執(zhí)行在另一個(gè)線程執(zhí)行結(jié)束后再繼續(xù)執(zhí)行,這時(shí)可以調(diào)用join()方法實(shí)現(xiàn),join()方法有下面三種格式:

    ·         public void join() throws InterruptedException 使當(dāng)前線程暫停執(zhí)行,等待調(diào)用該方法的線程結(jié)束后再執(zhí)行當(dāng)前線程。

    ·         public void join(long millis) throws InterruptedException 最多等待millis毫秒后,當(dāng)前線程繼續(xù)執(zhí)行。

    ·         public void join(long millis, int nanos) throws InterruptedException 可以指定多少毫秒、多少納秒后繼續(xù)執(zhí)行當(dāng)前線程。

    上述方法使當(dāng)前線程暫停執(zhí)行,進(jìn)入阻塞狀態(tài),當(dāng)調(diào)用線程結(jié)束或指定的時(shí)間過后,當(dāng)前線程線程進(jìn)入就緒狀態(tài),例如執(zhí)行下面代碼:

    t.join();

    將使當(dāng)前線程進(jìn)入阻塞狀態(tài),當(dāng)線程t執(zhí)行結(jié)束后,當(dāng)前線程才能繼續(xù)執(zhí)行。

    ④ 線程調(diào)用了wait()方法,等待某個(gè)條件變量,此時(shí)該線程進(jìn)入阻塞狀態(tài)。直到被通知(調(diào)用了notify()notifyAll()方法)結(jié)束等待后,線程回到就緒狀態(tài)。

    另外如果線程不能獲得對(duì)象鎖,也進(jìn)入就緒狀態(tài)。

    后兩種情況在下一節(jié)討論。



















    posted @ 2011-09-01 21:43 Jamie 閱讀(4001) | 評(píng)論 (0)編輯 收藏

    復(fù)習(xí)下java多線程

    好久沒搞這個(gè)了,今天把以前的筆記整理下,當(dāng)復(fù)習(xí)。

    Thread類和Runnable接口

    多線程是一個(gè)程序中可以有多段代碼同時(shí)運(yùn)行,那么這些代碼寫在哪里,如何創(chuàng)建線程對(duì)象呢?

        首先,我們來看Java語言實(shí)現(xiàn)多線程編程的類和接口。在java.lang包中定義了Runnable接口和Thread類。

     

    Runnable接口中只定義了一個(gè)方法:

    ·         public abstract void run()

    這個(gè)方法要由實(shí)現(xiàn)了Runnable接口的類實(shí)現(xiàn)。Runnable對(duì)象稱為可運(yùn)行對(duì)象,一個(gè)線程的運(yùn)行就是執(zhí)行該對(duì)象的run()方法。


          Thread
    類實(shí)現(xiàn)了Runnable接口,因此Thread對(duì)象也是可運(yùn)行對(duì)象。同時(shí)Thread類也是線程類,該類的常用構(gòu)造方法如下:

    ·         public Thread()

    ·         public Thread(Runnable target)

    ·         public Thread(String name)

    ·         public Thread(Runnable target, String name)
    target為線程運(yùn)行的目標(biāo)對(duì)象,即線程調(diào)用start()方法啟動(dòng)后運(yùn)行那個(gè)對(duì)象的run()方法,該對(duì)象的類型為Runnable,若沒有指定目標(biāo)對(duì)象,則以當(dāng)前類對(duì)象為目標(biāo)對(duì)象,name為線程名


     

      線程的創(chuàng)建 

    介紹下如何創(chuàng)建和運(yùn)行線程的兩種方法。線程運(yùn)行的代碼就是實(shí)現(xiàn)了Runnable接口的類的run()方法或者是Thread類的子類的run()方法,因此構(gòu)造線程體就有兩種方法:
        ·         繼承Thread類并覆蓋它的run()方法;
        ·        
    實(shí)現(xiàn)Runnable接口并實(shí)現(xiàn)它的run()方法。

      1,繼承Thread類創(chuàng)建線程

    通過繼承Thread類,并覆蓋run()方法,這時(shí)就可以用該類的實(shí)例作為線程的目標(biāo)對(duì)象。下面的程序定義了SimpleThread類,它繼承了Thread類并覆蓋了run()方法。

    程序SimpleThread.java

    public class SimpleThread extends Thread{

      public SimpleThread(String str){

        super(str);

    }

    public void run(){

        for(int i=0; i<100; i++){

          System.out.println(getName()+" = "+ i);

          try{

             sleep((int)(Math.random()*100));

          }catch(InterruptedException e){}

        }

    System.out.println(getName()+ " DONE");

    }

    }

    _____________________________________________________________________________

        SimpleThread類繼承了Thread類,并覆蓋了run()方法,該方法就是線程體。

    程序 ThreadTest.java

    public class ThreadTest{

      public static void main(String args[]){

        Thread t1 = new SimpleThread("Runner A");

        Thread t2 = new SimpleThread("Runner B");

        t1.start();

        t2.start();

     }

    }

    _____________________________________________________________________________

    ThreadTest類的main()方法中創(chuàng)建了兩個(gè)SimpleThread類的線程對(duì)象并調(diào)用線程類的start()方法啟動(dòng)線程。構(gòu)造線程時(shí)沒有指定目標(biāo)對(duì)象,所以線程啟動(dòng)后執(zhí)行本類的run()方法。

    注意,實(shí)際上ThreadTest程序中有三個(gè)線程同時(shí)運(yùn)行,在應(yīng)用程序的main()方法啟動(dòng)時(shí),JVM就創(chuàng)建一個(gè)主線程,在主線程中可以創(chuàng)建其他線程。

      2,實(shí)現(xiàn)Runnable接口創(chuàng)建線程

    可以定義一個(gè)類實(shí)現(xiàn)Runnable接口,然后將該類對(duì)象作為線程的目標(biāo)對(duì)象。實(shí)現(xiàn)Runnable接口就是實(shí)現(xiàn)run()方法。

    下面程序通過實(shí)現(xiàn)Runnable接口構(gòu)造線程體。

    程序 ThreadTest.java

    class T1 implements Runnable{

      public void run(){

        for(int i=0;i<15;i++)

          System.out.println("Runner A="+i);

      }

    }

    class T2 implements Runnable{

      public void run(){

        for(int j=0;j<15;j++)

          System.out.println("Runner B="+j);

      }

    }

    public class ThreadTest{

      public static void main(String args[]){

        Thread t1=new Thread(new T1(),"Thread A");

        Thread t2=new Thread(new T2(),"Thread B");

        t1.start();

        t2.start();

      }

    }

    _____________________________________________________________________________




        

     



    posted @ 2011-09-01 20:46 Jamie 閱讀(383) | 評(píng)論 (0)編輯 收藏

    android 項(xiàng)目下文件的作用

    1, R.java 是建立項(xiàng)目時(shí)自動(dòng)生成的,只讀,用來定義該項(xiàng)目所有資源的索引文件。
    這里面定義了很多常量, 名字與res文件夾的文件名和String.xml里的定義的常量名相同。當(dāng)項(xiàng)目中加入了新的資源時(shí),只需要刷新一下該項(xiàng)目,R.java 便自動(dòng)生成了。
    2, strings.xml 里面定義了字符串資源。 
        在類中可通過如下方式使用這些資源, Resource r = this.getContext().getResources(); String str = ((String) r.getString(R.string.name));
        在main.xml中可以 android:text="@string/name"
    3,  mail.xml 用來寫UI(布局,控件...)
        主程序繼承Activity類,重寫了void onCreate(Bundle savedInstanceState)方法。 在方法里通過setContentView(R.layout.main)設(shè)置Activity要顯示的布局文件(\layout\main.xml)
    4.  AndroidManifest.xml
        看下默認(rèn)的:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="      package="com.test"
          android:versionCode="1"
          android:versionName="1.0">
        <uses-sdk android:minSdkVersion="8" />

        <application android:icon="@drawable/icon" android:label="@string/app_name">   //應(yīng)用程序的名字
            <activity android:name=".WuActivity"   //默認(rèn)啟動(dòng)哪個(gè)Activity
                      android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>

        </application>
    </manifest>

    posted @ 2011-08-24 02:33 Jamie 閱讀(1024) | 評(píng)論 (0)編輯 收藏

    關(guān)于ADT和SDK版本

    用最新的就都用最新的, 不然有可能導(dǎo)致配置過程中出現(xiàn)一些問題。

    我用SDK3.2和ADT 0.9.5配置, 結(jié)果Preferences->Android里設(shè)置路徑出現(xiàn)問題。

    posted @ 2011-08-23 17:45 Jamie 閱讀(250) | 評(píng)論 (0)編輯 收藏

    Content is not allowed in prolog

    錯(cuò)誤可能是由XML有中文格式的字符引起的。

    posted @ 2011-04-20 08:43 Jamie 閱讀(285) | 評(píng)論 (0)編輯 收藏

    Jree

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

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

     

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

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

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

            return出口處   
          }也許你很迷惑這與樹遍歷算法有和關(guān)系,告訴你吧這三個(gè)特殊部位就是你在設(shè)計(jì)遞歸時(shí),遞歸函數(shù)應(yīng)該出現(xiàn)的位置,他們出現(xiàn)在不同的位置就是不同的“序”,偽碼如:
    先序遍歷
    traversTree(Node root){
       if(root !=null){
         if(root.isLeaf()){//當(dāng)是葉子時(shí),
             visit(root);//前序遍歷是先遍歷頁節(jié)點(diǎn)
         }   
             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ù)之后。
       }

    }

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

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

    因?yàn)槟P秃鸵晥D都能夠觸發(fā)事件,比如視圖(JTree等控件)是觸發(fā)用戶輸入導(dǎo)致的事件,而模型觸發(fā)的事件是因?yàn)槟P椭芯S護(hù)的數(shù)據(jù)有所變動(dòng)才觸發(fā)的(比如,樹模型中樹節(jié)點(diǎn)的增刪,改,或樹路徑的變動(dòng))。而他們都使用了觀察者模式,算了不多說了,到時(shí)全弄成模式了,會(huì)搞昏大家的。繼續(xù)....

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

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

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

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

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

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

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

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


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

    *****
    ******
    簡單的示例,我這里僅用到了最簡單的樹構(gòu)造方法,和一個(gè)監(jiān)聽器,在
    以后我的自學(xué)過程中,我會(huì)繼續(xù)試用其他的JTree知識(shí),我的JTree學(xué)習(xí)
    最終都是想實(shí)現(xiàn)那個(gè)GUI上的授權(quán)控制系統(tǒng),請(qǐng)參考其他篇章,
    至于這里用到的LAndFSysMenu類,在我的其他篇章中有該類的實(shí)現(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準(zhǔn)備顯示的模型*/
    Object[] m1=new String[]{"節(jié)點(diǎn)1","節(jié)點(diǎn)2","節(jié)點(diǎn)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實(shí)例:*/
       private JPanel treeDemo2(){
        JPanel rsltPanel=new JPanel();
        rsltPanel.setLayout(new BorderLayout());
       
        JLabel jl_msg=new JLabel("此標(biāo)簽用來顯示樹選擇情況");
        JScrollPane jsp_1=new JScrollPane();
        Object[] m=new String[]{"節(jié)點(diǎn)1","節(jié)點(diǎn)2","節(jié)點(diǎn)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)部類實(shí)現(xiàn)樹監(jiān)聽器,在樹被選中后將選中的節(jié)點(diǎn)
        //信息打印到一個(gè)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é)點(diǎn)是樹路徑上最后一個(gè)節(jié)點(diǎn)
         Object selectedNode=nodes[nodes.length-1 ];
         if(this.jl_msg!=null){
         this.jl_msg.setText("選中的節(jié)點(diǎn)上的文本是:"+
             selectedNode.toString());
         }
    }


       }
       /*另一組JTree實(shí)例:>>*/
    }

     

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

    posted @ 2011-03-23 09:09 Jamie| 編輯 收藏

    JTree用法

    import  java.awt.Dimension;
    import  java.awt.Color;
    import  javax.swing.JFrame;
    import  javax.swing.JPanel;
    import  javax.swing.JScrollPane;
    import  javax.swing.JTree;
    import  javax.swing.BoxLayout;
    import  javax.swing.tree.TreePath;
    import  javax.swing.tree.DefaultMutableTreeNode;
    import  javax.swing.tree.DefaultTreeModel;
    /*
    JTree的構(gòu)造函數(shù):
    JTree()
    JTree(Hashtable value)
    JTree(Object[] value)//只有這個(gè)構(gòu)造函數(shù)可以創(chuàng)建多個(gè)根結(jié)點(diǎn)
    JTree(TreeModel newModel)
    JTree(TreeNode root)
    JTree(TreeNode root, boolean asksAllowsChildren)
    JTree(Vector value)

    */
    public   class  JTreeDemo
    {
     
    public   static   void  main (String[] args)
     {


      
    // 構(gòu)造函數(shù):JTree()
      JTree example1  =   new  JTree();

     

      
      
    // 構(gòu)造函數(shù):JTree(Object[] value)
      Object[] letters =  { " a " " b " " c " " d " " e " };
      JTree example2 
    =   new  JTree (letters);

     


      
    // 構(gòu)造函數(shù):JTree(TreeNode root)(TreeNode空)
      
    // 用空結(jié)點(diǎn)創(chuàng)建樹
      DefaultMutableTreeNode node1  =   new  DefaultMutableTreeNode(); // 定義樹結(jié)點(diǎn)
      JTree example3  =   new  JTree (node1); // 用此樹結(jié)點(diǎn)做參數(shù)調(diào)用 JTree的構(gòu)造函數(shù)創(chuàng)建含有一個(gè)根結(jié)點(diǎn)的樹

     


      
    // 構(gòu)造函數(shù):JTree(TreeNode root)(同上,只是TreeNode非空)
      
    // 用一個(gè)根結(jié)點(diǎn)創(chuàng)建樹
      DefaultMutableTreeNode node2  =   new  DefaultMutableTreeNode( " Color " );
      JTree example4 
    =   new  JTree (node2); // 結(jié)點(diǎn)不可以顏色,默認(rèn)為白面黑字
      example4.setBackground (Color.lightGray);

     


      
    // 構(gòu)造函數(shù):JTree(TreeNode root, boolean asksAllowsChildren)(同上,只是TreeNode又有不同)
      
    // 使用DefaultMutableTreeNode類先用一個(gè)根結(jié)點(diǎn)創(chuàng)建樹,設(shè)置為可添加孩子結(jié)點(diǎn),再添加孩子結(jié)點(diǎn)
      DefaultMutableTreeNode color  =   new  DefaultMutableTreeNode( " Color " true );
      DefaultMutableTreeNode gray 
    =   new  DefaultMutableTreeNode ( " Gray " );
      color.add (gray);
      color.add (
    new  DefaultMutableTreeNode ( " Red " ));
      gray.add (
    new  DefaultMutableTreeNode ( " Lightgray " ));
      gray.add (
    new  DefaultMutableTreeNode ( " Darkgray " ));
      color.add (
    new  DefaultMutableTreeNode ( " Green " ));
      JTree example5 
    =   new  JTree (color);
      
      
      
      
      
    // 構(gòu)造函數(shù):JTree(TreeNode root)(同上,只是TreeNode非空)
      
    // 通過逐個(gè)添加結(jié)點(diǎn)創(chuàng)建樹
      DefaultMutableTreeNode biology  =   new  DefaultMutableTreeNode ( " Biology " );
      DefaultMutableTreeNode animal 
    =   new  DefaultMutableTreeNode ( " Animal " );
      DefaultMutableTreeNode mammal 
    =   new  DefaultMutableTreeNode ( " Mammal " );
      DefaultMutableTreeNode horse 
    =   new  DefaultMutableTreeNode ( " Horse " );
      mammal.add (horse);
      animal.add (mammal);
      biology.add (animal);
      JTree example6 
    =   new  JTree (biology);
      horse.isLeaf();
      horse.isRoot();
      
      


      
    // 構(gòu)造函數(shù):JTree(TreeModel newModel)
      
    // 用DefaultMutableTreeNodel類定義一個(gè)結(jié)點(diǎn)再用這個(gè)結(jié)點(diǎn)做參數(shù)定義一個(gè)用DefaultTreeMode
      
    // 創(chuàng)建一個(gè)樹的模型,再用JTree的構(gòu)造函數(shù)創(chuàng)建一個(gè)樹
      
      DefaultMutableTreeNode root 
    =   new  DefaultMutableTreeNode ( " Root1 " );
      DefaultMutableTreeNode child1 
    =   new  DefaultMutableTreeNode ( " Child1 " );
      DefaultMutableTreeNode child11 
    =   new  DefaultMutableTreeNode ( " Child11 " );
      DefaultMutableTreeNode child111 
    =   new  DefaultMutableTreeNode ( " Child111 " );
      root.add (child1); child1.add (child11); child11.add (child111);
      
      
      
      DefaultTreeModel model 
    =   new  DefaultTreeModel (root);
      
      JTree example7 
    =   new  JTree (model);

     

      JPanel panel 
    =   new  JPanel();
      panel.setLayout (
    new  BoxLayout (panel, BoxLayout.X_AXIS));
      panel.setPreferredSize (
    new  Dimension ( 700 400 ));
      panel.add (
    new  JScrollPane (example1)); // JTree必須放在JScrollPane上
      panel.add ( new  JScrollPane (example2));
      panel.add (
    new  JScrollPane (example3));
      panel.add (
    new  JScrollPane (example4));
      panel.add (
    new  JScrollPane (example5));
      panel.add (
    new  JScrollPane (example6));
      panel.add (
    new  JScrollPane (example7));
      

     

      JFrame frame 
    =   new  JFrame ( " JTreeDemo " );
      frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
      frame.setContentPane (panel);
      frame.pack();
      frame.show();
     }
    }
    ××××××××××××××××××××××××××××××××××××××××××××××

    在實(shí)際開發(fā)過程中會(huì)經(jīng)常使用JTree組件,平時(shí)會(huì)遇到這樣或那樣的問題,在此將偶得一點(diǎn)經(jīng)驗(yàn)寫下來,與大家共享,希望對(duì)大家有所幫助。

    private JTree jtNetDevice;//數(shù)組件申明
    private JScrollPane jspTree;//滾動(dòng)面板申明


    1、初始化
        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("root");
        jtNetDevice = new JTree(rootNode);
        jtNetDevice.setAutoscrolls(true);
        getTreeSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);//設(shè)置單選模式
        jspTree = new JScrollPane();
        jspTree.getViewport().add(jtNetDevice, null);

    2、三個(gè)經(jīng)常使用的取值函數(shù)
      private DefaultTreeModel getTreeModel(){
        return (DefaultTreeModel)jtNetDevice.getModel();
      }

      private DefaultMutableTreeNode getRootNode(){
        return (DefaultMutableTreeNode)getTreeModel().getRoot();
      }
     
      private TreeSelectionModel getTreeSelectionModel(){
        return jtNetDevice.getSelectionModel();
      }
     

    3、根據(jù)node得到path:
      TreePath visiblePath = new TreePath(getTreeModel().getPathToRoot(node));

    4、根據(jù)Path展開到該節(jié)點(diǎn)
      jtNetDevice.makeVisible(visiblePath);

    5、根據(jù)path設(shè)定該節(jié)點(diǎn)選定
      jtNetDevice.setSelectionPath(visiblePath);

    6、選中節(jié)點(diǎn)的方法
      首先,根據(jù)節(jié)點(diǎn)得到樹路徑,其中chosen為需要選中的節(jié)點(diǎn)
      TreePath visiblePath = new TreePath( ( (DefaultTreeModel) jtNetDevice.getModel()).
                                            getPathToRoot(chosen));
      然后根據(jù)Path選中該節(jié)點(diǎn)
      jtNetDevice.setSelectionPath(visiblePath);

    7、滾動(dòng)到可見位置
      jtNetDevice.scrollPathToVisible(visiblePath);

    8、給JTree添加右鍵彈出菜單
      void jtNetDevice_mouseReleased(MouseEvent e) {
        if (e.isPopupTrigger()) {
          jPopupMenu1.show(e.getComponent(), e.getX(), e.getY());//彈出右鍵菜單
        }
      }

    9、關(guān)于JTree的展開
       // If expand is true, expands all nodes in the tree.
       // Otherwise, collapses all nodes in the tree.
       public void expandAll(JTree tree, boolean expand) {
           TreeNode root = (TreeNode)tree.getModel().getRoot();
      
           // Traverse tree from root
           expandAll(tree, new TreePath(root), expand);
       }
       private void expandAll(JTree tree, TreePath parent, boolean expand) {
           // Traverse children
           TreeNode node = (TreeNode)parent.getLastPathComponent();
           if (node.getChildCount() >= 0) {
               for (Enumeration e=node.children(); e.hasMoreElements(); ) {
                   TreeNode n = (TreeNode)e.nextElement();
                   TreePath path = parent.pathByAddingChild(n);
                   expandAll(tree, path, expand);
               }
           }
      
           // Expansion or collapse must be done bottom-up
           if (expand) {
               tree.expandPath(parent);
           } else {
               tree.collapsePath(parent);
           }
       }
     

    10、如何遍歷JTree
       // 創(chuàng)建樹
       JTree tree = new JTree();
      
       // 添加樹節(jié)點(diǎn)......
      
       // 遍歷所有節(jié)點(diǎn)
       visitAllNodes(tree);
      
       // 僅遍歷展開的節(jié)點(diǎn)
       visitAllExpandedNodes(tree);
      
       // Traverse all nodes in tree
       public void visitAllNodes(JTree tree) {
           TreeNode root = (TreeNode)tree.getModel().getRoot();
           visitAllNodes(root);
       }
       public void visitAllNodes(TreeNode node) {
           // node is visited exactly once
           process(node);
      
           if (node.getChildCount() >= 0) {
               for (Enumeration e=node.children(); e.hasMoreElements(); ) {
                   TreeNode n = (TreeNode)e.nextElement();
                   visitAllNodes(n);
               }
           }
       }
      
       // Traverse all expanded nodes in tree
       public void visitAllExpandedNodes(JTree tree) {
           TreeNode root = (TreeNode)tree.getModel().getRoot();
           visitAllExpandedNodes(tree, new TreePath(root));
       }
       public void visitAllExpandedNodes(JTree tree, TreePath parent) {
           // Return if node is not expanded
           if (!tree.isVisible(parent)) {
               return;
           }
      
           // node is visible and is visited exactly once
           TreeNode node = (TreeNode)parent.getLastPathComponent();
           process(node);
      
           // Visit all children
           if (node.getChildCount() >= 0) {
               for (Enumeration e=node.children(); e.hasMoreElements(); ) {
                   TreeNode n = (TreeNode)e.nextElement();
                   TreePath path = parent.pathByAddingChild(n);
                   visitAllExpandedNodes(tree, path);
               }
           }
       }


    posted on 2006-04-04 17:24 SIMONE 閱讀(9202) 評(píng)論(1)  編輯  收藏 所屬分類: JAVA

    posted @ 2011-03-23 08:32 Jamie 閱讀(1729) | 評(píng)論 (0)編輯 收藏

    主站蜘蛛池模板: 免费一级特黄特色大片 | 日本免费xxxx色视频| 亚洲综合无码AV一区二区| 免费在线观看一区| 免费无遮挡无码永久在线观看视频| 亚洲国产最大av| 在线看免费观看AV深夜影院| 亚洲国产亚洲片在线观看播放| 91精品免费在线观看| 亚洲制服丝袜在线播放| 免费下载成人电影| 亚洲日韩AV一区二区三区四区| 免费人成视频在线| 亚洲日本中文字幕天天更新| 国产一区二区三区无码免费| 国产亚洲精品成人久久网站 | 99无码人妻一区二区三区免费| 亚洲一区免费在线观看| 天天干在线免费视频| 国产成人综合亚洲绿色| 狠狠亚洲狠狠欧洲2019| 一区二区三区观看免费中文视频在线播放 | 九九99热免费最新版| 久久久久久久综合日本亚洲| 中文字幕免费在线观看| 亚洲熟女综合色一区二区三区 | 国产亚洲大尺度无码无码专线| 久久免费国产精品| 亚洲欧洲日产韩国在线| 在线免费不卡视频| 国产免费MV大全视频网站| 亚洲AV人人澡人人爽人人夜夜| 大学生一级毛片免费看| 男男gvh肉在线观看免费| 亚洲av无码乱码国产精品fc2| 免费观看美女用震蛋喷水的视频| 亚洲Av永久无码精品黑人| 亚洲国产婷婷六月丁香| 青春禁区视频在线观看直播免费| 特级做a爰片毛片免费看| 噜噜噜亚洲色成人网站∨|