這是實用版 Gui88Abc.java 與 Gui888.java
加入了 捲動式選單 List, 
與下拉式選單 JComboBox 
  Gui88Abc.java (in gn88abc.jar) 仍需要 MyApplet.java 
  Gui888.java (in gn888.jar) 不需要 MyApplet.java 
 因為把用到處理圖檔部份 copy 到 Gui888.java 內了

  另外, JComboBox 是 Swing Library 的 GUI 元件,
   ( J 開頭的是 Swing Library 的) 
注意我故意用 ActionListener 監聽該 JComboBox cbSex 元件!
在 AWT 內與它類似的是 java.awt.Choice
  可是 java.awt.Choice 不可以用 ActionListener 監聽! 
必須用 ItemListener 監聽! 
   這裡我的 ItemListener (在 class MyDog 內)只有監聽 List 捲動式選單,
所以在處理函數 itemStateChanged(ItemEvent e) 內,
並沒有檢查 event 來自何處!



兩個版本功能完全一樣, 以下是當作 Application 跑的圖片

這是 gn888.jar
這是 gn88abc.jar

D:\jtest> linenum < Gui888.java 
   01 //Gui888.java -- Gui888 sample, @CopyLeft by tsaiwn@cs.nctu.edu.tw
   02 //這範例不需用到 MyApplet.java,
   03 // .. 因為需要關於圖檔部份已經 copy 在此檔案內
   04 //Java 建議: class name 第一個字用大寫字母!
   05 //Java 建議: 函數與變數用小寫開頭, 常數(就是final的變數)用全部大寫字母
   06 //package ...;  // 指定我這 class 的命名空間 namespace, 阿就是要放哪個目錄啦
   07 import java.applet.*;
   08 import java.awt.*;
   09 import java.awt.event.*;
   10 import javax.swing.*;
   11 import java.net.*;  // URL is in there
   12   // 注意要寫 public class 不然  Applet 有問題
   13 public class Gui888 extends Applet implements ActionListener { // 我就是 Applet
   14    // 希望讓個函數都看到的就放在這 Global 變數
   15    static boolean isApplication = false;  // in case that we need it
   16    Panel ppp;    // 木板 (面板)
   17    Button bbb;   // 按鈕
   18    TextArea ttA;    // 文字區
   19    TextField tx;   // 文字一列的欄
   20    JComboBox cbSex;  // 下拉式選單 Combo Box
   21    static final String MY_WEB = 
   22        "http://www.cs.nctu.edu.tw/~tsaiwn/oop/java/"  +
   23        "03_sample_JavaPrograms/13_soundwin/";
   24 
   25    public static void main(String gg[ ]) {     // Java 的主程式都這樣寫
   26        isApplication = true;
   27        JFrame f = new JFrame("Windows 2011");        // 開個窗 f
   28        f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
   29        // JFrame 可以設成按右上角的 X 會關窗, 這樣不必自己處理  WindowEvent !
   30        Gui888 me = new Gui888( );  // 模仿 Applet .. // 生出自己 (class Gui888 )
   31        f.add(me, "Center");   // 把 Applet (me) 放入窗 f 內
   32        f.setSize(885, 598);   // Frame 是 Window, 用 BorderLayout
   33        me.init( );      // 因為 Applet 被生出後先做 init( );
   34        me.start( );     // ..    再做  start( )
   35        f.setVisible(true);   // f.show( );
   36    } // main(
   37 
   38    static void println(String fmt, Object... oo) { print(fmt+"\n", oo); }
   39    static void print(String fmt, Object... oo){System.out.printf(fmt, oo); }
   40    static void printf(String fmt, Object... oo){System.out.printf(fmt, oo); }
   41    /// JDK1.5 (5.0)開始才有 printf( ) 
   42 
   43    static int rand( ) { return (int) (32768* Math.random( ) ); }
   44    static void srand(int x) { ; }
   45  
   46    public Gui888( ) { 
   47        super( );   // 可以不寫
   48        println(" Now doing ...  Gui888 constructor !");
   49    } // Constructor; 注意要寫 public 不然  Applet 有問題
   50 
   51    int kk = 0;  // Global variable to this class
   52    public void paint(Graphics g) {
   53        System.out.println(" In  paint kk = " + kk++);
   54        // do drawing something ...
   55        validate( );  //
   56        tx.requestFocus( );      //////////////  NEW7
   57    } // paint(
   58 
   59 //////////////// ====== //////////// 只是看看何時會跑過來這些函數
   60    public void start( ) {
   61        super.start( );
   62        println(" Now in start( ) ... kk = " + kk++);
   63    }// start(
   64    public void update(Graphics g) {  // 只是看看何時會跑過來這
   65        System.out.println(" update ==> kk = " + kk++);
   66        super.update(g); //  叫用上層(super class)的 update( )
   67    } // update(  will called by repaint( )
   68    public void stop( ) {
   69        println(" STOP into stop( ) ... kk = " + kk++);
   70        super.stop( );
   71    }// stop(
   72    public void destroy( ) {
   73        println(" Destroy into destroy( ) ... kk = " + kk++);
   74        super.destroy( );
   75    }// destroy(
   76   ////////   //////// //////// ////// ////// //////// ////////
   77 
   78    public void init( ) {
   79        tx=new TextField("你可以在這打字", 38);
   80        ppp = new Panel(  );  // Panel default using  FlowLayout
   81        bbb = new Button(" empty 按這裡看看 ");
   82        bbb.setFont(new Font("標楷體",1,36));  // 粗體 
   83        bbb.setCursor( new Cursor(Cursor.HAND_CURSOR) );  // 出現"手"
   84        ppp.setBackground(Color.pink);    // 背景色 粉紅
   85        //ppp.add(bbb);   // 把 bbb 按鈕塞入 ppp 木板 
   86        ///ppp.setSize(280, 120);    // 好像沒有用ㄟ ?
   87 
   88        decoratePpp(ppp, bbb);  // 重新安排 bbb 看板在 ppp 位置
   89        setLayout(new BorderLayout( ) );  // change Layout Manager 擺設經理
   90          // 因為 Applet 是 Panel, 其 default Layout Manager 是 FlowLayout
   91           // 設為  BorderLayout 後就可以指定 東西南北中  五個方位 放入元件
   92        add(ppp, "North");    /// ppp 放 我 (Gui888,  是Applet)的 北邊
   93 
   94        ttA = new TextArea("Hahaha\n", 5,20,TextArea.SCROLLBARS_BOTH);
   95        ttA.setFont(new Font("Ariel",3,32));   // 字體大一些; 3 = 粗 + 斜
   96        add(ttA, "Center");  /// ttA 文字區塊 放 我 (Gui888,是Applet)的中間
   97        Panel pOut = new Panel( ); 
   98        add(pOut, "South");   // 把 pOut 塞入我(Gui888)這個 Applet 南邊
   99 
  100        Panel pn = new Panel( ); 
  101        Panel ptt=new Panel( );
  102        pOut.setLayout(new BorderLayout( ));   // 外匡面版用 BorderLayout
  103        pOut.add(pn, "South");  // pn 塞在  pOut 這 Panel 內 :-) 木板上再放木板!
  104        pOut.add(ptt,"North");  // pOut 內塞兩個 Panel : pn, ptt
  105        //  現在 pOut 木板上有兩塊木板:  ptt 上; 下邊(南)是 pn  
  106 
  107        //tx.setFont(new Font("標楷體",1,28));  //  1 == Font.BOLD 粗體
  108        txSetting( );  // set attribute of tx (TextField)
  109        sexSet( );
  110        ptt.add(cbSex);  // 選性別
  111        ptt.add(new Label("請在右邊打字: "));     // 放入 ptt
  112        ptt.add(tx);      // 依序 放入 ptt
  113 
  114       /// 再來, pn 這木板上 放入很多按鈕 ! 所以用 array 陣列 比較方便 !
  115        pn.setBackground(Color.yellow); 
  116 
  117       // 再來要塞入一堆按鈕到 pn, 注意 pn 塞在 pOut 南邊(下方啦)
  118 
  119        putBtns2Pn( pn );
  120        bt[3].setForeground(Color.red);       ////// 紅字
  121        bt[2].setForeground(Color.BLUE); 
  122        bt[2].setBackground(Color.green); 
  123        bt[2].setCursor( new Cursor(Cursor.HAND_CURSOR) );  // 出現"手"
  124 
  125        JPanel pLeft = new JPanel( new BorderLayout( ) );  //東西南北中
  126        add(pLeft, "West");   // 準備左邊塞入 含有 可捲動選單 List 的 Panel
  127 
  128        List theList = getMyList(ptt);   //  選單 List
  129                // 因為 ptt 不是  Global, 我要傳過去以後改它顏色  !
  130 
  131        putList2PLeft(pLeft, theList);
  132 
  133       // 勞作都做好了再 add??Listener()
  134        bbb.addActionListener(this);
  135        tx.addActionListener(this); // 由"這"class的 actionPerformed()處理
  136          // TextField 是在按下 ENTER 時觸發 ActionEvent
  137        MyDog mm = new MyDog(ptt, theList);   // ptt 傳過去因要看情況改 顏色
  138        theList.addItemListener (mm);
  139        cbSex.addActionListener(this); // 由"這"class的 actionPerformed()
  140        validate( );  //  做了一些對圖形元件 的動作記得要做這  validate( ); 
  141    } // init(
  142 
  143    private void txSetting( ) {
  144        tx.setForeground(Color.BLUE);
  145        tx.setFont(new Font("標楷體", Font.BOLD, 24) );  // 24x24
  146        // tx.setFocusable(false); /// false 使得無法 Focus, 滑鼠點也不行!
  147        ///
  148        String s = "" + tx.getText( ) ;
  149        int len = s.length( );
  150        tx.setCaretPosition(len);    ////////// NEW8  設游標到字串最右邊
  151        tx.requestFocus( );      //////////////  NEW7
  152    } //
  153    private void sexSet( ) {
  154        String[ ] sss = {"性別", "男生", "女生" };
  155        cbSex = new JComboBox( sss ); // 全丟進去就可
  156        cbSex.setBackground( new Color(238, 198, 168) );
  157        cbSex.setForeground( Color.BLUE );
  158        //cbSex.setFont(new Font("標楷體", 1, 24) );  // Font.BOLD就是 1
  159    } // sexSet(
  160 
  161    Button bt[ ];   // 宣告說 bt[ ]  是 Button 陣列 (array)
  162    String bMsg[ ] = {"000", "Bt001", "看其他範例",
  163        "哈哈哈會讀取輸入", "bt西西", "BT五", "六 六 大順 囉", "Bye"
  164         ,"張三", "李四", "十全十美"
  165      };  /// 結束一定要有分號, 因為大括號左方是 Data !
  166    private void putBtns2Pn( Panel pn ) {
  167        bt = new Button[98];  // 只會生出 98 個參考 (阿其實就是 C++ 的指標啦)
  168           // 上列生出 98 個 參考(Reference) 不會用很多記憶體 :-)
  169           // 實際上會生出幾個按鈕是由 bMsg.length 決定 (看下列)
  170        for(int i=1; i< bMsg.length; ++i) {     // 這樣寫是個好習慣!
  171                             // 因為你去改 bMsg 陣列增加元素也不用來改這裡  :-)
  172            bt[i] = new Button(bMsg[i]);  // 真正生出六個 Button (注意 0 故意不用)
  173            pn.add(bt[i]);
  174            bt[i].setFont(new Font("細明體",1,24));
  175                  // 注意上列是在做勞作 :-)  把按鈕加入 pn 木板 !
  176            bt[i].addActionListener(this);   // 請求監聽 "動作事件"(ActionEvent)
  177                // 注意上列是要求監聽 bb[i] 喔 !
  178        } // for int i
  179    } // putBtns2Pn(
  180 
  181    void putList2PLeft(JPanel pLeft, List theList) {  // 塞 可捲動式選單 List
  182        Label tmpLab = new Label("請選擇木板顏色");
  183        tmpLab.setFont(new Font("標楷體",1,18));   //////
  184        tmpLab.setForeground( Color.BLUE );  // 藍色 
  185        theList.setFont(new Font("細明體",1,16));
  186        pLeft.add(tmpLab, "North");
  187        pLeft.add(theList, "Center"); // 把 選單 塞入 Panel
  188        pLeft.setPreferredSize( new Dimension(128, 128) );
  189        pLeft.updateUI( );
  190    } // putList2PLeft(
  191 
  192 ////////   =============================================  //////////
  193    Color yyc[ ] = { Color.red, Color.blue, Color.green, Color.pink
  194        , Color.magenta, Color.cyan, new Color(198, 38, 198), Color.gray
  195    };  // 結束一定要有分號, 因為大括號左方是 Data !
  196    int cid = -1;   // 以便 +1 後變成 0 開始
  197 
  198    void processBBB( ) {   // 用另一個 Thread 跑它
  199        javax.swing.SwingUtilities.invokeLater(new Runnable( ) {
  200           public void run() {
  201              cid =  (cid+1) % yyc.length;
  202              bbb.setForeground( yyc[cid] ); 
  203              repaint( );
  204              return;
  205           } // run(
  206        }); // javax...
  207    } // processBBB( 
  208    void processSex(Object who) {
  209        JComboBox box = (JComboBox)who;   // cast 其實沒做事:-)
  210        int k = box.getSelectedIndex( ); 
  211        int kk = k;
  212        String gg = "你確定要隨性嗎?";
  213        switch(k) {  // do NOT forget that will falling through
  214            case 0: gg = "R U sure " + gg;  kk=7; break; //灰色
  215            case 1: gg = "你要選大男人的號碼喔!"; break;
  216            case 2: gg = "女人比較好嗎?"; kk=4; // magenta
  217        }//switch
  218        ttA.append( gg + "\n");
  219        ttA.setForeground( yyc[kk] );
  220        repaint( );
  221    } // processSex(
  222 
  223    public void actionPerformed(ActionEvent e) {
  224        Object who = e.getSource( );    // 誰被按了一下 ?
  225        String gg = "You press " + e.getActionCommand( );
  226 
  227        if(who == bt[7]) System.exit(0);
  228        if(who == bt[2]) {openWebWindow( MY_WEB ); return; }
  229 
  230        if(who == bbb) {
  231           processBBB( );  return;
  232        }// 用另一個 Thread 跑它(若事情很多)
  233        if(who == cbSex) {
  234            processSex(who); return;
  235        }
  236 
  237        if(who == bt[1]) ppp.setBackground(Color.red);
  238        if(who == bt[6]) {  // 六六大順
  239            ppp.setBackground(Color.green);
  240            ttA.append("如果 林志玲 來演講, 你會去聽嗎? ");
  241        } // if
  242 
  243        bbb.setLabel(gg);    /// change 看板 bbb 的字
  244        ttA.append(gg+"\n");
  245        if(who == bt[3] || who == tx)  {   // Read data in tx
  246            ttA.append("讀到 " + tx.getText( ) + "\n");
  247            ppp.setBackground(Color.pink);
  248        } // if
  249        repaint( );  // 會偷叫 update(Graphics);
  250    } // actionPerformed( 
  251 
  252  ////////////
  253    void decoratePpp(Panel ppp, Button btnToShow) {
  254        JLabel labJiang =   // 抄自 MyApplet.java(extends 就不必copy)
  255           createLabelWithPicture("img/mypic.gif", "猜猜我是誰");
  256        ppp.setLayout( new BorderLayout( ) ); // 改用東西南北中擺法
  257        ppp.add(labJiang, "West");    // 左 (江蕙)
  258     ///
  259        Panel p3= new Panel( new BorderLayout( ) );
  260          Panel p3Up = new Panel( );  
  261          Panel p3Down = new Panel( );
  262           p3.add(p3Up, "North");    // 塞一些空間 :-)
  263           p3.add(p3Down, "South");
  264           p3.add(btnToShow, "Center");
  265       ///
  266        p3Down.setPreferredSize(new Dimension(200,98) );
  267        p3Up.setPreferredSize(new Dimension(200,38) );
  268       ////////////
  269        JPanel tmpPan = new JPanel( new BorderLayout( ) ); // !!!
  270        // tmpPan.add( something, "West");  // Left side 
  271        tmpPan.add(p3, "Center"); //
  272        tmpPan.setBackground( new Color(198, 0, 168) );
  273      /// /// //再把tmpPan塞入ppp木板Center但右邊沒東西
  274        ppp.add(tmpPan, "Center");  
  275    } // decoratePpp(
  276 
  277    List getMyList(Panel p) {  // 這 p 是要讓我改顏色的 Panel 
  278        List pcList = new List( );  // Panel Color selective List
  279        String cName[ ] = { "紅色", "橙色", "黃色", "綠色"
  280           ,"藍色", "靛 (淡藍)", "紫色", "灰(gray)"
  281           ,"紅色", "橙色", "黃色", "綠色"
  282           ,"藍色", "靛 (淡藍)", "紫色", "灰(gray)"
  283           ,"紅色", "橙色", "黃色", "綠色"
  284          ,"藍色"};
  285        for( String gg: cName) pcList.add( gg );  // 依序加入各顏色名稱
  286        pcList.setBackground(Color.pink);
  287        pcList.setFont(new Font("標楷體 ", 1, 28) ); // 粗體
  288        int kr = 5; /// 預設 color
  289        pcList.select(kr);  // current default 選 5-th
  290        p.setBackground(selColor[kr]);  // 先弄成 5-th color ?
  291        return pcList;
  292    } // getMyList(
  293 
  294    void openWebWindow(String web) {  // note different when in Application
  295        try {
  296           if(isApplication){  // utilize the Runtime exec function
  297              try {              // 注意格式, 因字串中含有 " 雙引號 "
  298                 Runtime.getRuntime( ).exec(
  299                   "cmd /c \"start " + web + "\" " );
  300              } catch (Exception e95){  // try Win 95/98
  301                 Runtime.getRuntime( ).exec(
  302                   "start " + web );   //Win95/98中 start 是內建
  303              }// try..catch..
  304           } else { // is Applet, we are in Browser, use showDocument( )
  305              URL url = new URL(web); 
  306              getAppletContext().showDocument(url, "_blank"); 
  307           }   // see AppletContext      // _blank means in New Window
  308        } catch (Exception e) {; }
  309    } // openWebWindow(  
  310 
  311 /////////////////////////////////////////////////////////////////////
  312 /////////////////////////////////////////////////////////////////////
  313    JLabel createLabelWithPicture(String filename) {
  314        return createLabelWithPicture(filename, "", 
  315                             javax.swing.SwingConstants.TRAILING);
  316    }
  317    JLabel createLabelWithPicture(String filename, String caption) {
  318        return createLabelWithPicture(filename, caption, 
  319                             javax.swing.SwingConstants.TRAILING);
  320    }
  321    JLabel createLabelWithPicture(String filename, String caption,
  322                                                   int alignment ) {
  323       JLabel ans = null;
  324       ImageIcon icon = null;
  325       try {
  326          Image image = myGetImageBoth(filename);
  327          icon = new ImageIcon( image ); 
  328          ans = new JLabel(caption, icon, alignment);
  329          ans.setVerticalTextPosition(
  330                             javax.swing.SwingConstants.BOTTOM);
  331          ans.setHorizontalTextPosition(
  332                             javax.swing.SwingConstants.CENTER);
  333       } catch (Exception e) {
  334          try { if(ans==null) ans = new JLabel(caption);
  335          } catch (Exception e2) {;}
  336       }
  337       return ans;
  338    } // createLabelWithPicture(
  339    Image getImageBoth(String filename) {
  340        return myGetImageBoth( filename);
  341    }
  342    Image myGetImageBoth(String filename) {
  343       Image image = null;
  344       try {       // Application 中讀取 Image 方法與 Applet 中不同
  345          image = newImageBoth(filename);   //try Application first
  346          //println("MyApplet got image=" + image);
  347       } catch (Exception e) { image=null; // then, try Applet
  348       } // try .. catch
  349       if(image==null) {
  350          try {       // try Applet, Applet use different method
  351             image = getImage(new URL( getCodeBase()+ filename));
  352          } catch (Exception e) { image = null;}
  353       } //if
  354       if(image != null) return image;  //////////////////
  355       try { // ok, now the last way I can try
  356          Toolkit tkt = Toolkit.getDefaultToolkit( );
  357          Class me = getClass( );   // get The class which is running
  358          URL url = me.getResource(filename);
  359          image = tkt.getImage( url ); // works for both Application+Applet
  360       } catch (Exception e) { image = null; } // sorry, I have no way
  361       return image; 
  362    } // myGetImageBoth
  363 ///
  364    public  Image  newImageBoth(String filename) {   /// NOT static
  365        Image image = null;
  366        try {   // 2011/04/02  good in Jar file
  367           Toolkit tkt = Toolkit.getDefaultToolkit( );
  368           Class me = getClass( );   // get The class is running
  369           URL url = me.getResource(filename);
  370           image = tkt.getImage(url); 
  371        } catch (Exception e) { ; }
  372        return image;
  373    } // newImageBoth(String 
  374 /////////////////////////////////////////////////////////////////
  375 /////////////////////////////////////////////////////////////////
  376  
  377    class MyDog implements ItemListener {    //////// NEW 4 in Gui888.java
  378        Panel pp = null;
  379        List choose = null;
  380        MyDog(Panel p, List s) { pp = p; choose = s; }
  381          // Inner class 看得到外部 class 的 Global 變數, 
  382          /// 但看不到 在函數內的 Local 變數!
  383          /// 若放 Global 就可以不必傳啦 !
  384        public void itemStateChanged(ItemEvent e) {
  385           if(pp==null) return; // 防呆 :-)
  386           Object who = e.getItem( );  // Item number #
  387           // so far 只處理該 List
  388           int sel = choose.getSelectedIndex( );   // OK too
  389           pp.setBackground( selColor[ sel ] );
  390           pp.getParent( ).getParent( ).repaint( );
  391        } // itemStateChanged(
  392    } // class MyDog   (an inner class)  
  393    static Color selColor[ ] = 
  394      { Color.red, Color.orange, Color.YELLOW, Color.green
  395           ,Color.BLUE, Color.cyan, Color.magenta, Color.gray
  396           ,Color.red, Color.orange, Color.YELLOW, Color.green
  397           ,Color.BLUE, Color.cyan, Color.magenta, Color.gray
  398           ,Color.red, Color.orange, Color.YELLOW, Color.green
  399           ,Color.BLUE
  400      }; // selColor[ ]
  401 } // class

D:\jtest>