第二十章 圖型介面與網路對播 (GUI and Intercross Transition) 20-1 簡介 20-2 ActionListener Interface 20-3 ActionEvent Class 20-4 Vector Class 20-5 圖型介面與視窗關閉 20-6 圖型介面與資料顯示 Server/Client 對播程式設計 20-8 習題 (Exercises)
20-1 簡介 本書已於第十五章探討網路對播之程式架構與設 計,於十九章探討視窗圖型界面,本章將綜合此 兩章之內容,設計一組網路對播之視窗圖型界面, 讓使用者輕鬆有效地操作網路對播。
20-2 ActionListener Interface java.awt.event.ActionListener 為公用介面 (Public Interface) ,此介面用於回應 Action 動作,通常以方 法程序 addActionListener(this) 將事件之傾聽功能加 入特定位置物件,再以方法程序 actionPerformed() 配合發生在該位置物件之滑鼠或鍵盤事件,優先執 行之,即暫停執行其他執行緒 (Threads) 或行程 (Processes) 。 ( 如範例 158)
範例 158 :設計檔案 Ex20_2.java 其功能為解釋方法程序 addActionListener(this) 、 actionPerformed() 之應用。 01 import java.awt.*; 02 import java.awt.event.*; 03 class Ex20_2 extends Frame implements ActionListener { 04 public Ex20_2() { 05 super("myFrame"); 06 TextField tfS = new TextField("South Area"); 07 add(tfS, BorderLayout.SOUTH); 08 TextField tfC = new TextField("Center Area"); 09 add(tfC, BorderLayout.CENTER);
範例 158 :續 1 10 setSize(350, 300); 11 setVisible(true); 12 tfS.addActionListener(this); 13 } 14 public static void main(String[] args) { 15 Ex20_2 teststart = new Ex20_2(); 16 } 17 public void actionPerformed(ActionEvent evt) { 18 System.out.println("An ActionEvent occurred on tfS"); 19 } 20 }
20-3 ActionEvent Class java.awt.event.ActionEvent 繼承 (extends) 自 AWTEvent → EventObject → Object ,此類別可 建立事件物件,通常都以前節之方法程序 actionPerformed(ActionEvent evt) 配合執行,當 系統有事件發生時,參數 evt 自動產生 ( 如範例 158 、 159) 。
範例 159 :設計檔案 Ex20_3.java 其功能為解釋事件物件與方法程序 getSource() 之應用。 01 import java.awt.*; 02 import java.awt.event.*; 03 class Ex20_3 extends Frame implements ActionListener { 04 TextField input_Area = new TextField(); 05 TextField record_Area = new TextField(); 06 public Ex20_3() { 07 super("myFrame"); 08 add(input_Area, BorderLayout.SOUTH); 09 add(record_Area, BorderLayout.CENTER);
範例 159 :續 1 10 setSize(350, 300); 11 setVisible(true); 12 input_Area.addActionListener(this); 13 } 14 public static void main(String[] args) { 15 Ex20_3 teststart = new Ex20_3(); 16 } 17 public void actionPerformed(ActionEvent evt) { 18 if(evt.getSource() == input_Area) { 19 System.out.println("An ActionEvent occurred on input_Area"); 20 } 21 } 22 }
20-4 Vector Class java.util.Vector 繼承 (extends) 自 Object ,此類 別可建立向量物件,類似陣列 (Array) ,却較 陣列更具彈性: (1) 各元素可使用任意物件, 不像陣列、必須是相同的資料型態; (2) 可 自動調整適當長度,不像陣列、必須是設 定長度 ( 如範例 160) 。
範例 160 :設計檔案 Ex20_4_1.java 其功能為解釋系統可自動調整向 量物件成適當長度;使用者也可選擇性地設定其長度。 01 import java.util.*; 02 class Ex20_4_1 { 03 public Ex20_4_1() { 04 Vector vec1 = new Vector(0); 05 System.out.println("vec1 Initial Capacity = " + vec1.capacity()); 06 vec1.addElement("Here is No.0 Line"); 07 vec1.addElement("Here is No.1 Line"); 08 vec1.addElement("Here is No.2 Line"); 09 System.out.println("vec1 Adjusted Capacity = " + vec1.capacity());
範例 160 :續 1 10 Vector vec2 = new Vector(0, 50); 11 System.out.println("vec2 Initial Capacity = " + vec2.capacity()); 12 vec2.addElement("Here is No.0 Line"); 13 vec2.addElement("Here is No.1 Line"); 14 vec2.addElement("Here is No.2 Line"); 15 System.out.println("vec2 Adjusted Capacity = " + vec2.capacity()); 16 } 17 public static void main(String[] args) { 18 Ex20_4_1 teststart = new Ex20_4_1(); 19 } 20 }
範例 161 :設計檔案 Ex20_4_1.java 其功能為解釋類別 Vector 各實體方法程序之應用。 01 import java.util.*; 02 class Ex20_4_2 { 03 public Ex20_4_2() { 04 Vector vec = new Vector(); 05 vec.addElement("Here is No.0 Line"); 06 vec.addElement("Here is No.1 Line"); 07 vec.addElement("Here is No.2 Line");
範例 161 :續 1 08 System.out.println("isEmpty() : " + vec.isEmpty()); 09 System.out.println("elementAt(1) : " + vec.elementAt(1)); 10 System.out.println("firstElement(0) : " + vec.firstElement()); 11 System.out.println("lastElement(0) : " + vec.lastElement()); 12 vec.insertElementAt("Here is the insert Object", 1); 13 System.out.println("elementAt(1) : " + vec.elementAt(1)); 14 } 15 public static void main(String[] args) { 16 Ex20_4_2 teststart = new Ex20_4_2(); 17 } 18 }
範例 162 :設計檔案 Ex20_5.java 其功能為解釋關閉視窗程式碼之設計。 01 import java.awt.*; 02 import java.awt.event.*; 03class Ex20_5 extends Frame { 04 public Ex20_5() { 05 super("myFrame"); 06 setSize(300, 350); 07 setVisible(true); 08 addWindowListener(new WindowAdapter() { 09 public void windowClosing(WindowEvent evt) { 10 System.exit(0); 11 } 12 }); 13 } 14 public static void main(String[] args) { 15 Ex20_5 teststart = new Ex20_5(); 16 } 17 }
範例 163 :設計檔案 Ex20_6.java 其功能為解釋圖型介面各項功能之設計。 01 import java.awt.*; 02 import java.awt.event.*; 03 import java.util.*; 04 class Ex20_6 extends Frame implements ActionListener { 05 TalkRoom TalkRecord = new TalkRoom(); 06 TextField TalkInput = new TextField(); 07 public Ex20_6() { 08 super("myFrame"); 09 try{ 10 add(TalkRecord, BorderLayout.CENTER); 11 add(TalkInput, BorderLayout.SOUTH); 13 TalkInput.addActionListener(this);
範例 163 :續 1 14 setSize(500, 350); 15 setVisible(true); 16 addWindowListener(new WindowAdapter() { 17 public void windowClosing(WindowEvent evt) { 18 System.exit(0); 19 } 20 }); 21 } 22 catch (Exception e) { 23 System.out.println(e.getMessage()); 24 } 25 }
範例 163 :續 2 26 public void actionPerformed(ActionEvent evt) { 27 if (evt.getSource() == TalkInput) { 28 try { 29 TalkRecord.PrintTalk(TalkInput.getText(), Color.red); 30 } catch (Exception e) { 31 System.out.println(e.getMessage()); 32 } 33 TalkInput.setText(null); 34 } 35 } 36 public static void main(String args[]) { 37 Ex20_6 ServerStart=new Ex20_6(); 38 } 39 }
範例 163 :續 3 40 class TalkRoom extends Component { 41 Vector PastLine = new Vector(); 42 Vector NewLine = new Vector(); 43 synchronized void PrintTalk(String s, Color c) { 44 NewLine.addElement(new SaveLine(s, c)); 45 repaint(); 46 } 47 public void paint(Graphics g) { 48 synchronized (this) { 49 while (NewLine.size() > 0) { 50 PastLine.addElement(NewLine.elementAt(0)); 51 NewLine.removeElementAt(0); 52 } 53 while (PastLine.size() > 40) { 54 PastLine.removeElementAt(0); 55 } 56 } 57 FontMetrics fontM = g.getFontMetrics();
範例 163 :續 4 58 int margin = fontM.getHeight()/2; 59 int w = getSize().width; 60 int y = getSize().height-fontM.getHeight()-margin; 61 for (int i=PastLine.size()-1; i>=0; i--) { 62 SaveLine ShowLine = (SaveLine)PastLine.elementAt(i); 63 g.setColor(ShowLine.clr); 64 g.setFont(new Font(ShowLine.str,Font.BOLD,12)); 65 g.drawString(ShowLine.str, margin, y+fontM.getAscent()); 66 y -= fontM.getHeight(); 67 } 68 } 69 } 70 class SaveLine { 71 String str; 72 Color clr; 73 SaveLine(String str, Color clr) { 74 this.str = str; 75 this.clr = clr; 76 } 77 }
範例 164 :設計檔案 Server20_7.java 、 Client20_7.java 其功能為解釋 圖型介面網路對播之應用。 檔案 Server20_7.java : 001 import java.awt.*; 002 import java.awt.event.*; 003 import java.io.*; 004 import java.net.*; 005 import java.util.*; 006 class Server20_7 extends Frame implements ActionListener, Runnable { 007 TalkRoom TalkRecord = new TalkRoom(); 008 TextField TalkInput = new TextField(); 009 ServerSocket SSocket; 010 Socket socket; 011 static int port; 012 DataOutputStream outstream; 013 DataInputStream instream;
範例 164 :續 public Server20_7() { 015 super("Server"); 016 try{ 017 SSocket = new ServerSocket(port); 018 System.out.println("Server is created and waiting Client to connect..."); 019 socket = SSocket.accept(); 020 System.out.println("Client IP = " + socket.getInetAddress().getHostAddress()); 021 outstream = new DataOutputStream(socket.getOutputStream()); 022 instream = new DataInputStream(socket.getInputStream()); 023 add(TalkRecord, BorderLayout.CENTER); 024 add(TalkInput, BorderLayout.SOUTH); 025 TalkInput.addActionListener(this); 026 addWindowListener(new WindowAdapter() {
範例 164 :續 public void windowClosing(WindowEvent evt) { 028 System.exit(0); 029 } 030 }); 031 setSize(500, 350); 032 setVisible(true); 033 new Thread(this).start(); 034 } 035 catch (Exception e) { 036 e.printStackTrace(); 037 } 038 } 039 public void actionPerformed(ActionEvent evt) { 040 if (evt.getSource() == TalkInput) { 041 try { 042 outstream.writeUTF("Server> "+TalkInput.getText()); 043 TalkRecord.PrintTalk(TalkInput.getText(), Color.red); 044 } catch (Exception e) { 045 TalkRecord.PrintTalk("Connection is Interrupted", Color.green); 046 } 047 TalkInput.setText(null); 048 } 049 }
範例 164 :續 public void run() { 051 try { 052 while (true) { 053 String NetTransferLine = instream.readUTF(); 054 TalkRecord.PrintTalk(NetTransferLine, Color.black); 055 } 056 } 057 catch (Exception e) { 058 TalkRecord.PrintTalk("Connection is Interrupted!", Color.green); 059 } 060 } 061 public static void main(String args[]) { 062 if (args.length < 1){ 063 System.out.println("USAGE: java Server20_7 [port]"); 064 System.exit(1); 065 } 066 port=Integer.parseInt(args[0]); 067 Server20_7 ServerStart=new Server20_7(); 068 } 069 }
範例 164 :續 class TalkRoom extends Component { 071 Vector PastLine = new Vector(); 072 Vector NewLine = new Vector(); 073 synchronized void PrintTalk(String s, Color c) { 074 NewLine.addElement(new SaveLine(s, c)); 075 repaint(); 076 } 077 public void paint(Graphics g) { 078 synchronized (this) { 079 while (NewLine.size() > 0) { 080 PastLine.addElement(NewLine.elementAt(0)); 081 NewLine.removeElementAt(0); 082 } 083 while (PastLine.size() > 40) { 084 PastLine.removeElementAt(0); 085 } 086 }
範例 164 :續 FontMetrics fontM = g.getFontMetrics(); 088 int margin = fontM.getHeight()/2; 089 int w = getSize().width; 090 int y = getSize().height-fontM.getHeight()-margin; 091 for (int i=PastLine.size()-1; i>=0; i--) { 092 SaveLine ShowLine = (SaveLine)PastLine.elementAt(i); 093 g.setColor(ShowLine.clr); 094 g.setFont(new Font(ShowLine.str,Font.BOLD,12)); 095 g.drawString(ShowLine.str, margin, y+fontM.getAscent()); 096 y -= fontM.getHeight(); 097 } 098 } 099 } 100 class SaveLine { 101 String str; 102 Color clr; 103 SaveLine(String str, Color clr) { 104 this.str = str; 105 this.clr = clr; 106 } 107 }
範例 164 :續 6 檔案 Client20_7.java : 108 import java.awt.*; 109 import java.awt.event.*; 110 import java.io.*; 111 import java.net.*; 112 import java.util.*; 113 class Client20_7 extends Frame implements ActionListener, Runnable { 114 TalkRoom TalkRecord = new TalkRoom(); 115 TextField TalkInput = new TextField(); 116 Socket socket; 117 static String iaddr; 118 static int port; 119 DataOutputStream outstream; 120 DataInputStream instream;
範例 164 :續 public Client20_7() { 122 super("Client"); 123 try{ 124 socket=new Socket(InetAddress.getByName(iaddr),port); 125 outstream = new DataOutputStream(socket.getOutputStream()); 126 instream = new DataInputStream(socket.getInputStream()); 127 add(TalkRecord, BorderLayout.CENTER); 128 add(TalkInput, BorderLayout.SOUTH); 129 TalkInput.addActionListener(this); 130 addWindowListener(new WindowAdapter() { 131 public void windowClosing(WindowEvent evt) { 132 System.exit(0); 133 } 134 });
範例 164 :續 setSize(500, 350); 136 setVisible(true); 137 new Thread(this).start(); 138 } 139 catch (Exception e) { 140 e.printStackTrace(); 141 } 142 } 143 public void actionPerformed(ActionEvent evt) { 144 if (evt.getSource() == TalkInput) { 145 try { 146 outstream.writeUTF("Client> "+TalkInput.getText()); 147 TalkRecord.PrintTalk(TalkInput.getText(), Color.red); 148 } catch (Exception e) { 149 TalkRecord.PrintTalk("Connection is Interrupted", Color.green); 150 } 151 TalkInput.setText(null); 152 } 153 }
範例 164 :續 public void run() { 155 try { 156 while (true) { 157 String NetTransferLine = instream.readUTF(); 158 TalkRecord.PrintTalk(NetTransferLine, Color.black); 159 } 160 } 161 catch (Exception e) { 162 TalkRecord.PrintTalk("Connection is Interrupted!", Color.green); 163 } 164 } 165 public static void main(String args[]) { 166 if (args.length < 2){ 167 System.out.println("USAGE: java Client20_7 [iaddr] [port]"); 168 System.exit(1); 169 } 170 iaddr = args[0]; 171 port=Integer.parseInt(args[1]); 172 Client20_7 ClientStart=new Client20_7(); 173 } 174 } 175 class TalkRoom extends Component {
範例 164 :續 Vector PastLine = new Vector(); 177 Vector NewLine = new Vector(); 178 synchronized void PrintTalk(String s, Color c) { 179 NewLine.addElement(new SaveLine(s, c)); 180 repaint(); 181 } 182 public void paint(Graphics g) { 183 synchronized (this) { 184 while (NewLine.size() > 0) { 185 PastLine.addElement(NewLine.elementAt(0)); 186 NewLine.removeElementAt(0); 187 } 188 while (PastLine.size() > 40) { 189 PastLine.removeElementAt(0); 190 } 191 }
範例 164 :續 FontMetrics fontM = g.getFontMetrics(); 193 int margin = fontM.getHeight()/2; 194 int w = getSize().width; 195 int y = getSize().height-fontM.getHeight()-margin; 196 for (int i=PastLine.size()-1; i>=0; i--) { 197 SaveLine ShowLine = (SaveLine)PastLine.elementAt(i); 198 g.setColor(ShowLine.clr); 199 g.setFont(new Font(ShowLine.str,Font.BOLD,12)); 200 g.drawString(ShowLine.str, margin, y+fontM.getAscent()); 201 y -= fontM.getHeight(); 202 } 203 } 204 }
範例 164 :續 class SaveLine { 206 String str; 207 Color clr; 208 SaveLine(String str, Color clr) { 209 this.str = str; 210 this.clr = clr; 211 } 212 }