Tập bài giảng Lập trình Java (Phần 2)

pdf 119 trang Gia Huy 17/05/2022 4080
Bạn đang xem 20 trang mẫu của tài liệu "Tập bài giảng Lập trình Java (Phần 2)", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdftap_bai_giang_lap_trinh_java_phan_2.pdf

Nội dung text: Tập bài giảng Lập trình Java (Phần 2)

  1. CHƢƠNG 4: LẬP TRÌNH ĐỒ HOẠ AWT 4.1. Giới thiệu về AWT Các ứng dụng phần mềm hiện nay rất thân thiện vì được trình bày nhiều màn hình giao diện đồ họa đẹp. Các ngôn ngữ lập trình hiện nay cung cấp các đối tượng đồ họa, chúng có thể được điều khiển bởi người lập trình, hay bởi người sử dụng. Một trong số những kết quả quan trọng nhất chính là các ngôn ngữ hiện nay được dựa trên Giao diện người dùng đồ họa (Graphical User Interface - GUI). Trong chương này, ta sẽ thảo luận về Java hỗ trợ tính năng GUI cùng các sự thi hành của chúng. GUI cung cấp chức năng nhập liệu theo cách thân thiện với người dùng. GUI đa dạng từ ứng dụng đến ứng dụng và có thể chứa nhiều điều khiển như hộp văn bản, nhãn, hộp danh sách hay các điều khiển khác. Các ngôn ngữ lập trình khác nhau cung cấp nhiều cách khác nhau để tạo GUI. Các ngôn ngữ như VB hay VC++ có thể cung cấp chức năng kéo và thả trong khi đó phần mềm giống như C++ yêu cầu người lập trình phải viết toàn bộ mã để xây dựng GUI. Một phần tử (element) GUI được thiết lập bằng cách sử dụng thủ tục sau:  Tạo đối tượng  Xác định sự xuất hiện ban đầu của đối tượng  Chỉ ra nó nằm ở đâu  Thêm phần tử vào giao diện trên màn hình Một thành phần (component) GUI là một đối tượng trực quan. Người dùng tương tác với đối tượng này thông qua con trỏ chuột hay bàn phím. Các thành phần như là button, label có thể được nhìn thấy trên màn hình. Bất kỳ cái gì chung cho tất cả các thành phần GUI đều được tìm thấy trong lớp Component. Để tạo các đối tượng GUI chúng ta cần nhập gói java.awt. AWT là viết tắt của Abstract Windowing Toolkit. AWT là một bộ các lớp trong Java cho phép chúng ta tạo GUI và chấp nhận các nhập liệu của người dùng thông qua bàn phím và chuột. AWT cung cấp các thành phần khác nhau để tạo GUI hiệu quả và lôi cuốn người sử dụng. Các thành phần này có thể là:  Vật chứa (Container)  Thành phần (Component)  Trình quản lý cách trình bày (Layout manager)  Đồ họa (Graphic) và các tính năng vẽ (draw)  Phông chữ (Font)  Sự kiện (Event) Gói AWT chứa các lớp, giao diện và các gói khác. Hình sau đây mô tả một phần nhỏ của hệ thống phân cấp lớp AWT. 136
  2. Object CheckboxGroup MenuComponent BorderLayout Component FlowLayout GridLayout Hình 4.1. Hệ thống cây phân cấp lớp AWT 4.2. Container (vật chứa) 4.2.1. Giới thiệu Container là vùng mà bạn có thể đặt các thành phần giao diện của bạn vào đó. Bất cứ vật gì mà kế thừa từ lớp Container sẽ là vật chứa. Applet là một vật chứa, Applet được dẫn xuất từ Panel, lớp Panel lại được dẫn xuất từ lớp Container. Một vật chứa có thể chứa nhiều phần tử, các phần tử này có thể được vẽ hay được tô màu tuỳ thích. Bạn hãy xem vật chứa như một cửa sổ. Như khung (frame), panel, latch, hook, và các thành phần có kích thước nhỏ hơn khác. Gói java.awt chứa một lớp gọi là Container. Lớp này trực tiếp hay gián tiếp phải sinh ra hai vật chứa được sử dụng phổ biến nhất là Frame và Panel. Frame và Panel là các vật chứa thường được sử dụng. Frame là cửa sổ độc lập nhưng ngược lại Panel là vùng nằm trong cửa sổ khác. Panel không có các đường biên, chúng được trình bày trong một cửa sổ do trình duyệt hay appletviewer cung cấp. Appletviewer là một công cụ được JDK hỗ trợ để xem các Applet. Frame là lớp con của Window. Chúng được trình bày trong một cửa sổ độc lập, cửa sổ này có chứa các đường biên xung quanh. 4.2.2. Frame Frame không phụ thuộc vào Applet và trình duyệt. Frame có thể hoạt động như một vật chứa hay như một thành phần (component). Bạn có thể sử dụng một trong những constructor sau để tạo một frame:  Frame(): Tạo một frame nhưng không hiển thị (invisible)  Frame(String title): Tạo một frame không hiển thị, có tiêu đề. Ví dụ 4.1: Minh hoạ cách tạo một Frame. import java.awt.*; class FrameDemo extends Frame { public FrameDemo(String title) 137
  3. { super(title); } public static void main(String args[]) { FrameDemo f=new FrameDemo(“I have been Frameed!!!”); f.setSize(300,200); f.setVisible(true); } } Lớp được định nghĩa FrameDemo là một lớp con của lớp Frame. Lớp FrameDemo này có một phương thức khởi tạo, trong phương thức khởi tạo này ta cho gọi phương thức super(). Nó sẽ gọi phương thức khởi tạo của lớp cha (trong trường hợp này là Frame). Mục đích của super() là gọi phương thức khởi tạo của lớp cha. Nó sẽ tạo một đối tượng của lớp con, lớp con này sẽ tạo Frame. Tuy nhiên, Frame vẫn không nhìn thấy được và không có kích thước. Để làm được điều này, ta sử dụng hai phương thức nằm trong phương thức main: setSize() và setVisible(). Kết chạy của chương trình giống như hình 4.2 Hình 4.2. Kết quả chạy ví dụ 4.1 4.2.3. Panel Panel được sử dụng để nhóm một số các thành phần lại với nhau. Cách đơn giản nhất để tạo một panel là sử dụng phương thức khởi tạo của nó, hàm Panel(). Ví dụ 4.2:Chỉ ra cách tạo một panel: import java.awt.*; 138
  4. class PanelTest extends Panel { public static void main(String args[]) { Paneltest p=new Paneltest(); Frame f=new Frame(“Testing a Panel”); f.add(p); f.setSize(300,200); f.setVisible(true); } public Paneltest() { } } Panel không thể được nhìn thấy trực tiếp. Do đó, chúng ta cần thêm panel đến một frame. Vì vậy ta cần tạo một frame mới và thêm Panel mới được tạo này vào đó. Tuy nhiên, frame sẽ không nhìn thấy được, và không có kích thước. Chúng ta sử dụng hai phương thức trong phương thức main – setSize() và setVisible() để thiết lập kích thước và hiển thị frame. Kết xuất của chương trình: Hình 4.3. Kết quả chạy ví dụ 4.2 4.2.4. Dialog Lớp „Dialog‟ tương tự như lớp Frame, nghĩa là Dialog là lớp con của lớp Window. Đối tượng Dialog được tạo như sau: 139
  5. Frame myframe=new Frame(“My frame”); // calling frame String title = “Title”; boolean modal = true; // whether modal or not Dialog dlg=new Dialog(myframe, title, modal); Tham số „modal‟ chỉ ra rằng dialog sẽ ngăn chặn bất kỳ tương tác nào xảy đến với các cửa sổ được mở khác, trong khi dialog đang được hiển thị trên màn hình. Kiểu hộp thoại này ngăn chặn người dùng tương tác với các cửa sổ khác (của cùng ứng dụng) trên màn hình, cho tới khi dialog được đóng lại. 4.3. Thành phần (Component) 4.3.1. Giới thiệu Một component có thể được đặt trên giao diện người dùng, có thể được thay đổi kích thước hay làm cho nhìn thấy, ẩn. Ví dụ được dùng phổ biến nhất là Textfield, Label, Checkbox, Textarea v.v Và các thành phần cao cấp khác như Scrollbar, Scrollpane và Dialog. Tuy nhiên chúng không được sử dụng thường xuyên. TextField TextComponent TextArea Button C Label o m Checkbox p o n List e n Choice t Panel Applet Container Window Frame Canvas Dialog Scrollbar Hình 4.4. Các lớp thành phần Bây giờ chúng ta hãy xét một số thành phần thường được sử dụng. 4.3.2. Nhãn Lớp này được sử dụng để trình bày một String. Nó không thể được sửa đổi. Đây là một chuỗi chỉ đọc. Sử dụng một trong những constructor sau đây để tạo một label:  Label() Tạo một Label trống. 140
  6.  Label(String labeltext) Tạo một Label với nội dung được cho.  Label(String labeltext, int alignment) Tạo một Label với một chế độ canh lề (alignment) , canh lề có thể là Label.LEFT, Label.RIGHT hay Label.CENTER. Các phương thức được sử dụng phổ biến của label được trình bày ở bảng bên dưới: Phương thức Chức năng setFont(Font f) Thay đổi phông chữ của Label setText(String s) Thiết lập nhãn cho Label getText() Lấy nội dung hiện tại của nhãn Bảng 4.1. Các phương thức của Label Ví dụ 4.3:Về cách sử dụng của Label: import java.awt.*; class LabelTest extends Frame { Label label1=new Label(“This is just a label”); public LabelTest(String title) { super(title); add(label1); } } public static void main(String args[]) { LabelTest f=new LabelTest(“Label”); f.setSize(300,200); f.show(); } } label1=new Label(“This is just a label”); 141
  7. Label sẽ hiển thị chỉ khi nó được thêm vào Container. Ở đây, Frame là Container mà thành phần Label được thêm vào. Việc này được thực hiện bằng cách sử dụng phương thức add(). Khi chạy chương trình được kết quả hình 4.5 Hình 4.5. Kết quả chạy ví dụ 4.3 4.3.3. Ô văn bản Một Textfield là một vùng chỉ chứa một dòng văn bản, trong đó văn bản có thể được hiển thị hay được nhập vào bởi người dùng. Trong Java, một trong những constructor sau có thể được sử dụng để tạo một Textfield:  TextField(): Tạo một textfield mới.  TextField(int columns): Tạo một textfield mới với số cột được cho trước.  TextField(String s): Tạo một textfield mới với chuỗi văn bản được cho trước.  TextField(String s, int columns): Tạo một textfield mới với nội dung và số cột được cho trước. Các phương thức thường được sử dụng của đối tượng TextField được tóm tắt trong bảng sau: Phƣơng thức Chức năng setEchoChar(char) Đặt các kí tự được hiện ra thay thế ký tự nhập vào. setText(String s) Gán nội dung cho TextField. getText() Lấy nội dung của TextField. setEditable(boolean) Xác định TextField có soạn thảo được hay không. Nó chỉ được soạn thảo khi giá trị tham số truyền vào là True. isEditable() Xác định xem trường có đang trong mode soạn thảo hay không. Giá trị trả về kiểu Boolean. 142
  8. Bảng 4.2. Các phương thức của TextField Ví dụ 4.4: Cách sử dụng của TextField: import java.awt.*; class TextFieldTest extends Frame { TextField tf1=new TextField(30); public TextFieldTest(String title) { super(title); setLayout(new FlowLayout()); add(tf1); } public static void main(String args[]) { TextFieldTest f=new TextFieldTest(“TextField”); f.setSize(300,200); f.show(); } } Trong ví dụ nàycó sử dụng phương thức setLayout() để thay đổi cách trình bày của các thành phần trên vật chứa. Layout manager có chức năng sắp xếp các thành phần trong một vật chứa. Kết của chương trình được chỉ ra ở hình bên dưới: Hình 4.6. Kết quả chạy ví dụ 4.4 143
  9. 4.3.4. Vùng văn bản Một Textarea được sử dụng khi văn bản nhập vào có trên hai hay nhiều dòng. Textarea có một scrollbar. TextArea là một trường văn bản có thể được soạn thảo với nhiều dòng. Để tạo một Textarea, làm theo các bước sau: 1) Tạo một đối tượng. 2) Chỉ ra số dòng, số cột đối tượng này cần có. 3) Bố trí phần tử này trên màn hình. Trong Java, bạn có thể sử dụng các constructor sau để tạo TextArea:  TextArea(): Tạo một TextArea mới.  TextArea(int rows, int cols): Tạo một TextArea mới với số lượng cột và dòng được cho trước.  TextArea(String text): Tạo một TextArea mới với nội dung được cho trước.  TextArea(String text, int rows, int cols): Tạo một TextArea mới với dung, số dòng và số cột được cho trước. Các phương thức thường được sử dụng nhiều nhất của TextArea: Phƣơng thức Chức năng setText(String) Gán nội dung cho TextArea. getText() Trả về nội dung của TextArea. setEdiable(boolean) Xác định xem TextAreacó thể được soạn thảo hay không. TextArea có thể được soạn thảo khi giá trị này là True. isEditable() Xác định xem TextArea có đang trong chế độ soạn thảo được không. Trả về giá trị là kiểu Boolean. insertText(String, int) Chèn chuỗi được vào vị trí được cho trước. replaceText(String, int, int) Thay thế văn bản nằm giữa vị trí int, int cho trước. Bảng 4.3. Các phương thức của TextArea Ví dụ 4.5: Cách sử dụng của TextArea: import java.awt.*; class TextAreaTest extends Frame { Label lbl=new Label(“Details”); 144
  10. TextArea ta1=new TextArea(); public TextAreaTest(String title) { super(title); setLayout(new FlowLayout()); add(lbl); add(ta1); } public static void main(String args[]) { TextAreaTest t=new TextAreaTest(“TextArea”); t.setSize(300,200); t.show(); } } Kết quả của chương trình được chỉ ra ở hình bên dưới: Hình 4.7. Kết quả chạy ví dụ 4.5 4.3.5. Nút Nút ấn hay còn gọi là nút lệnh là một phần không thể thiếu của bất kỳ GUI nào. Sử dụng button là cách dễ nhất để nhận các tác động của người dùng. Để tạo một button, bạn làm theo các bước sau: 1) Tạo phần tử Button với một nhãn chỉ ra mục đích của Button. 2) Bố trí phần tử này trên màn hình. 3) Hiển thị phần tử trên màn hình. Sử dụng một trong hai constructor sau để tạo các button trong Java:  Button()  Button(String text) 145
  11. Sử dụng setLabel() và getLabel() để thiết lập và lấy giá trị nhãn của button. Ví dụ 4.6:Đơn giản sau đây sẽ tạo ra 3 button import java.awt.*; class ButtonTest extends Frame { Button b1 = new Button(“red”); Button b2 = new Button(“Green”); Button b3 = new Button(“Blue”); public ButtonTest(String title) { super(title); setLayout(new FlowLayout()); add(b1); add(b2); add(b3); } public static void main(String args[]) { ButtonTest t= new ButtonTest(“Button”); t.setSize(300,200); t.show(); } } Kết quả của chương trình được 146
  12. Hình 4.8. Kết quả chạy ví dụ 4.6 4.3.6. Checkbox và Radio Button Checkbox được sử dụng khi người dùng tiến hành chọn một hay nhiều tùy chọn. Người dùng phải click trên các Checkbox để chọn hay bỏ chọn chúng. Một Radio button cũng tương tự như một Checkbox. Nó được sử dụng như một Option button để xác định các chọn lựa. Bạn chỉ có thể chọn một Option trong nhóm các nút Radiobutton, ngược lại bạn có thể chọn nhiều hơn một Checkbox tại một thời điểm. Làm theo các bước sau để tạo các Checkbox hay Radiobutton: 1) Tạo phần tử. 2) Xác định trạng thái khởi đầu của phần tử (chọn hay không chọn). 3) Bố trí các phần tử trên màn hình. 4) Hiển thị các phần tử trên màn hình. Thành phần Checkbox có thể sử dụng một lớp phụ được gọi là CheckboxGroup để tạo ra các Radiobutton. Sử dụng các constructor sau để tạo các Checkbox trong Java:  Checkbox(): Tạo một Checkbox trống.  Checkbox(String text): Tạo một Checkbox với nhãn được cho. Để tạo các Radio button, đầu tiên chúng ta tạo đối tượng CheckboxGroup như sau: CheckboxGroup cg=new CheckboxGroup(); Sau đó chúng ta tạo các đối tượng, như sau: Checkbox male=new Checkbox(“male”, cg, true); Checkbox female=new Checkbox(“female”, cg, false); Chúng ta sử dụng các phương thức setState() và getState() để thiết lập và nhận về trạng thái của Checkbox. 147
  13. Ví dụ 4.7:Minh họa cách sử dụng của các Checkbox và các Radiobutton: import java.awt.*; class CheckBoxTest extends Frame { Label l1=new Label(“CheckBoxes”); Checkbox b1=new Checkbox(“red”,true); Checkbox b2=new Checkbox(“Green”,false); Checkbox b3=new Checkbox(“Blue”,false); Label l2=new Label(“Radiobuttons”); CheckboxGroup cb=new CheckboxGroup(); Checkbox b4=new Checkbox(“small”,cb,true); Checkbox b5=new Checkbox(“medium”,cb,false); Checkbox b6=new Checkbox(“large”,cb,false); public CheckBoxTest(String title) { super(title); setLayout(new GridLayout(8,1)); add(l1); add(b1); add(b2); add(b3); add(l2); add(b4); add(b5); add(b6); } public static void main(String args[]) { CheckBoxTest t=new CheckBoxTest(“Checkbox and radiobutton”); t.setSize(300,200); 148
  14. t.show(); } } Đầu tiên chúng ta tạo một đối tượng Frame, đối tượng này hoạt động như một Container sẽ chứa thành phần Checkbox mà ta đã tạo. Sau đó ta tạo 6 Checkbox, 02 Checkbox được đánh dấu chọn. Để làm được điều này, ta đưa giá trị true như một tham số cho hàm Contructor Checkbox, ngoài ra còn có một tham số String là nhãn của Checkbox. Để hiển thị các điều khiển này theo dạng lưới, ta phải thiết lập cách trình bày về dạng GridLayout có 8 dòng và 1 cột. Cuối cùng, ta tạo một biểu hiện cho lớp Checkboxtest và thiết lập kích thước cho Frame. Để hiển thị nó, ta cho gọi phương thức show(). Kết quả chạy chương trình ở hình bên dưới: Hình 4.9. Kết quả chạy ví dụ 4.7 4.3.7. Danh sách lựa chọn Thỉnh thoảng, rất cần thiết để trình bày một danh sách các chọn lựa đến người dùng trên một GUI. Người dùng có thể click vào một hay nhiều mục từ danh sách. Một danh sách chọn lựa được tạo bằng cách sử dụng một số các chuỗi (String) hay các giá trị văn bản. Để tạo các danh sách chọn lựa, hãy làm theo các bước được cho sau đây: 1) Tạo danh sách các phần tử. 2) Thêm các mục (có kiểu là String) vào danh sách, mỗi lần chỉ thêm được một mục. 3) Bố trí danh sách trên màn hình. 4) Hiển thị danh sách trên màn hình. 149
  15. Java hỗ trợ lớp Choice cho phép chúng ta tạo các danh sách chứa nhiều mục. Khi danh sách vừa được tạo ra, nó sẽ rỗng. Choice colors=new Choice(); Mỗi thời điểm chỉ thêm được một item bằng cách sử dụng phương thức addItem như được chỉ ra bên dưới: colors.addItem(“Red”); colors.addItem(“Green”); Ví dụ 4.8:Minh họa cách tạo một danh sách chọn lựa: import java.awt.*; class ChoiceTest extends Frame { Label l1=new Label(“What is your favorite color”); Choice colors=new Choice(); public ChoiceTest(String title) { super(title); setLayout(new FlowLayout()); add(l1); colors.addItem(“White”); colors.addItem(“Red”); colors.addItem(“Orange”); colors.addItem(“Green”); colors.addItem(“Yellow”); colors.addItem(“Blue”); colors.addItem(“Black”); add(colors); } public static void main(String args[]) { ChoiceTest t=new ChoiceTest(“Choice list”); 150
  16. t.setSize(300,200); t.show(); } } Kết quả chạy chương trình ta được: Hình 4.10. Kết quả chạy ví dụ 4.8 4.4. Quản lý cách trình bày Layout manager điều khiển cách trình bày vật lý của các phần tử GUI như là button, textbox, option button v.v Một layout manager tự động bố trí các thành phần này trong Container. Các kiểu trình bày khác nhau:  Flow layout  Border layout  Card layout  Grid layout  GridBag Layout Tất cả các thành phần mà chúng ta vừa tạo sử dụng layout manager mặc định. Cho ví dụ, „FlowLayout‟ là cách trình bày mặc định của một Applet. Layout manager này sẽ tự động sắp xếp các thành phần. Tất cả các thành phần được đặt trong một Container, và được sắp xếp nhờ layout manager tương ứng. Layout manager được thiết lập bằng phương thức „setLayout()‟. Bây giờ chúng ta sẽ tìm hiểu chi tiết các cách trình bày và cách bố trí các thành phần của ta vào những vị trí mong muốn. 151
  17. 4.4.1. FlowLayout manager „FlowLayout‟ là layout manager mặc định cho Applet và Panel. Các thành phần được sắp xếp từ góc trái trên đến góc phải dưới của màn hình. Khi một số thành phần được tạo, chúng được sắp xếp theo hàng, từ trái sang phải. Các constructor của FlowLayout: FlowLayout mylayout = new FlowLayout() // constructor //constructor with alignment specified FlowLayout exLayout=new FlowLayout(FlowLayout.RIGHT); setLayout(exLayout); //setting the layout to Flowlayout Các điều khiển có thể được canh về bên trái, bên phải hay ở giữa. Để canh các điều khiển về bên phải, bạn sử dụng cú pháp sau: setLayout(new FlowLayout(FlowLayout.RIGHT)); Ví dụ 4.9:Minh họa về FlowLayout manager. import java.awt.*; class FlTest extends Frame { Button b1=new Button(“Center Aligned Button 1”); Button b2=new Button(“Center Aligned Button 2”); Button b3=new Button(“Center Aligned Button 3”); public FlTest(String title) { super(title); setLayout(new FlowLayout(FlowLayout.CENTER)); add(b1); add(b2); add(b3); } public static void main(String args[]) { FlTest t=new FlTest(“Flow Layout”); t.setSize(300,200); 152
  18. t.show(); } } Kết chạy chương trình được: Hình 4.11. Kết quả chạy ví dụ 4.9 4.4.2. BorderLayout Manager „BorderLayout‟ là layout manager mặc định cho „Window‟, „Frame‟ và „Dialog‟. Layout này sắp xếp tối đa 5 thành phần trong một Container. Những thành phần này có thể được đặt ở các hướng „North‟, „South‟, „East‟, „West‟ và „Center‟ của Container.  NORTH – Đặt ở đỉnh của Container.  EAST – Đặt phía bên phải của Container.  SOUTH – Đặt ở phía dưới của Container.  WEST – Đặt phía bên trái của Container.  CENTER – Đặt ở giữa của Container. Để thêm một thành phần vào vùng „North‟, bạn sử dụng cú pháp sau: Button b1=new Button(“North Button”); // khai báo thành phần setLayout(new BorderLayout()); // thiết lập layout add(b1,BorderLayout.NORTH); // thêm thành phần vào layout Các thành phần vẫn giữ nguyên vị trí tương đối của chúng kể cả khi Container bị thay đổi kích thước. Các thành phần được đặt trong vùng „North‟, „South‟ được dàn nằm ngang trong khi đó các thành phần đặt trong vùng „East‟ và „West‟ lại được dàn thẳng đứng. Các thành phần được đặt trong vùng „Center‟ sẽ được dàn đều vào những khu vực nằm giữa của Container. add(b2,BorderLayout.CENTER); // thêm thành phần vào vùng „Center‟ 153
  19. Khi tất cả các thành phần được đặt vào các vùng tương ứng, lúc đó Frame sẽ giống như sau: Hình 4.12. BorderLayout BorderLayout có thể chứa nhiều hơn 5 thành phần. Để thực hiện điều này, chúng ta có thể sử dụng các Panel với các layout khác nhau để chứa các thành phần, và sau đó đặt các panel này vào trong BorderLayout. 4.4.3. Card Layout Manager CardLayout có thể lưu trữ một ngăn xếp (stack) các giao diện. Mỗi giao diện giống như một bảng (card). Bảng thường là đối tượng Panel. Một thành phần độc lập như button sẽ điều khiển cách trình bày các bảng ở lớp trên cùng. Đầu tiên, chúng ta bố trí tập hợp các thành phần được yêu cầu trên các panel tương ứng. Mỗi panel sẽ được bố trí vào các layout khác nhau. Ví dụ: panelTwo.setLayout(new GridLayout(2,1)); Panel chính sẽ chứa những panel này. Chúng ta thiết lập layout của panel chính là Cardlayout như sau: CardLayout card=new CardLayout(); panelMain.setLayout(card); Bước kế tiếp là thêm các panel khác vào panel chính: panelMain.add(“Red Panel”, panelOne); panelMain.add(“Blue Panel”, panelTwo); Phương thức „add()‟ sử dụng hai tham số. Tham số đầu tiên là một String làm nhãn của panel và tham số thứ hai là tên đối tượng Panel. Ví dụ 4.10:Minh họa CardLayout: import java.awt.*; 154
  20. import java.applet.*; /* */ public class CardLayoutDemo extends Applet { Button Back, next; Label lbl1,lbl2,lbl3,lbl4; TextField other1; Panel p1,first,second,third,fourth; CardLayout c1; public void init() { back=new Button(“Back”); next=new Button(“Next”); add(back); add(next); c1=new CardLayout(); p1=new Panel(); p1.setLayout(c1);// Set panel layout to CardLayout lbl1=new Label(“First”); lbl2=new Label(“Second”); lbl3=new Label(“Third”); lbl4=new Label(“Fourth”); //First panel first=new Panel(); first.add(lbl1); //Second panel second=new Panel(); second.add(lbl2); //Third panel third=new Panel(); 155
  21. third.add(lbl3); //Fourth panel fourth=new Panel(); fourth.add(lbl4); //Add panels to the card deck panel p1.add(“1”,first); p1.add(“2”,second); p1.add(“3”,third); p1.add(“4”,fourth); add(p1); } } Kết quả chạy chương trình được như sau: Hình 4.13. Kết quả chạy ví dụ 4.10 Trong hình bên trên, các panel được thêm vào panel chính như là các thẻ riêng biệt. Vì thế chỉ có thẻ đầu tiên mới được thấy trên màn hình. Nhưng người dùng có thể điều hướng sang các panel khác sử dụng các phương thức của CardLayout. 4.4.4. GridLayout Manager „GridLayout‟ trợ giúp việc chia Container vào trong ô lưới. Các thành phần được đặt trong các ô giao của dòng và cột. Mỗi lưới nên chứa ít nhất một thành phần. Một lưới được sử dụng khi tất cả các thành phần có cùng kích thước. GridLayout được tạo như sau: GridLayout g1=new GridLayout(4,3); 4 là số dòng và 3 là số cột. 156
  22. Ví dụ 4.11: Minh họa cách trình bày lưới: import java.awt.*; class GlTest extends Frame { Button btn[]; String str[]={“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”}; public GlTest(String title) { super(title); setLayout(new GridLayout(3,3)); btn=new Button[str.length]; for (int i=0; i<str.length;i++) { btn[i]=new Button(str[i]); add(btn[i]); } } public static void main(String args[]) { GlTest t=new GlTest(“Grid Layout”); t.setSize(300,200); t.show(); } } Kết xuất chương trình như sau: 157
  23. Hình 4.14. Kết quả chạy ví dụ 4.10 4.4.5. GridBagLayout Manager „GridBagLayout‟ là cách trình bày hiệu quả và phức tạp hơn bất cứ cách trình bày nào khác. Layout này đặt các thành phần vào vị trí chính xác. Với layout này, các thành phần không cần có cùng kích thước. Nó tương tự như GridLayout manager, khi các thành phần được sắp xếp trong lưới theo dòng và cột. Tuy nhiên, thứ tự đặt các thành phần không theo nguyên tắc từ trái sang phải và từ trên xuống dưới. GridBagLayout gb=new GridBagLayout() ContainerName.setLayout(gb); Để sử dụng layout này, bạn cần cung cấp thông tin về kích thước và vị trí của mỗi thành phần. Lớp „GridBagLayoutConstraints‟ chứa tất cả các thông tin mà lớp GridLayout cần để bố trí và định kích thước mỗi thành phần. Bảng sau liệt kê danh sách các biến thành viên của lớp GridBagConstraints: Các biến Mục đích thành viên weightx, Chỉ ra sự phân phối của khoảng trống trong GridBagLayout. Giá weighty trị mặc định cho các biến này là 0. gridwidth, Chỉ ra số lượng các ô (cell) chiều ngang và chiều dọc trong vùng gridheight hiển thị của một thành phần. ipadx, ipady Chỉ ra lượng làm thay đổi chiều cao và chiều rộng tối thiểu của thành phần. Nó sẽ thêm 2*ipadx vào chiều rộng tối thiểu và 2*ipady vào chiều cao tối thiểu của thành phần. Giá trị mặc định cho cả hai là 0. anchor Chỉ ra cách sắp xếp các thành phần trong cell. Mặc định sẽ đặt vào giữa cell. Các thành viên dữ liệu tĩnh (static) sau đây có thể 158
  24. được sử dụng: GridBagConstraints.NORTH GridBagConstraints.EAST GridBagConstraints.WEST GridBagConstraints.SOUTH GridBagConstraints.NORTHEAST GridBagConstraints.SOUTHEAST gridx, gridy Chỉ ra vị trí cell sẽ đặt thành phần. Khi thiết lập giá trị của gridx là „GridbagConstraints.RELATIVE‟ thì thành phần được thêm sẽ nằm ở vị trí bên phải của thành phần cuối cùng. fill Chỉ ra cách mà một thành phần được bố trí vào cell thế nào nếu như cell lớn hơn thành phần. Mặc định là kích thước thành phần không thay đổi. Bảng 4.4. Các biến thành viên của lớp GridBagConstraints Bảng sau đây cung cấp một danh sách các biến dữ liệu tĩnh là các giá trị cho biến fill: Giá trị Mô tả GridBagConstraints.NONE Mặc định, không làm thay đổi kích thước của thành phần. GridBagConstraints.HORIZONTAL Tăng chiều rộng của thành phần theo chiều ngang (HORIZONTAL) để làm cho thành phần khớp với chiều ngang. GridBagConstraints.VERTICAL Tăng chiều cao của thành phần theo chiều đứng (VERTICAL) để làm cho thành phần khớp với chiều dọc. GridBagConstraints.BOTH Tăng chiều rộng, chiều cao của thành phần theo cả chiều ngang và chiều dọc. insets Xác định khoảng cách top, Bottom, left và right giữa các thành phần. Mặc định là 0. Bảng 4.5. Các biến thành viên dữ liệu tĩnh của biến fill Sử dụng phương thức „setConstraints()‟ để thiết lập các hằng số cho mỗi thành phần. gblay.setConstraints(lb1, gbc); 159
  25. „gblay‟ là đối tượng của lớp GridBagLayout, lbl là thành phần „Label‟ và „gbc‟ là đối tượng của lớp GridBagConstraints. Ví dụ 4.12: Minh họa một ví dụ của GridBagLayout và GridBagConstraints. import java.awt.*; class GblTest extends Frame { TextArea ta; TextField tf; Button b1,b2; CheckboxGroup cbg; Checkbox cb1,cb2,cb3,cb4; GridBagLayout gb; GridBagConstraints gbc; public GblTest(String title) { super(title); gb=new GridBagLayout(); setLayout(gb); gbc=new GridBagConstraints(); ta=new TextArea(“Textarea”,5,10); tf=new TextField(“enter your name”); b1=new Button(“TextArea”); b2=new Button(“TextField”); cbg=new CheckboxGroup(); cb1=new Checkbox(“Bold”, cbg,false); cb2=new Checkbox(“Italic”, cbg,false); cb3=new Checkbox(“Plain”, cbg,false); cb4=new Checkbox(“Bold/Italic”, cbg,true); gbc.fill=GridBagConstraints.BOTH; addComponent(ta,0,0,4,1); 160
  26. gbc.fill=GridBagConstraints.HORIZONTAL; addComponent(b1,0,1,1,1); gbc.fill=GridBagConstraints.HORIZONTAL; addComponent(b2,0,2,1,1); gbc.fill=GridBagConstraints.HORIZONTAL; addComponent(cb1,2,1,1,1); gbc.fill=GridBagConstraints.HORIZONTAL; addComponent(cb2,2,2,1,1); gbc.fill=GridBagConstraints.HORIZONTAL; addComponent(cb3,3,1,1,1); gbc.fill=GridBagConstraints.HORIZONTAL; addComponent(cb4,3,2,1,1); gbc.fill=GridBagConstraints.HORIZONTAL; addComponent(tf,4,0,1,3); } public void addComponent(Component c, int row, int col, int nrow, int ncol) { gbc.gridx=col; gbc.gridy=row; gbc.gridwidth=ncol; gbc.gridheight=ncol; gb.setConstraints(c,gbc); add(c); } public static void main(String args[]) { Gbltest t=new Gbltest(“GridBag Layout”); t.setSize(300,200); t.show(); } 161
  27. } Khi một container bị thay đổi kích thước và khi khoảng trắng phụ tồn tại, các thành phần có chiều rộng lớn hơn sẽ chiếm giữ nhiều khoảng trống hơn là các thành phần có giá trị về chiều rộng nhỏ hơn. Kết quả chạy chương trình như sau: Hình 4.15. Kết quả chạy ví dụ 4.12 Giải thích đoạn mã trên: gbc.fill=GridBagConstraints.BOTH; Thành viên fill của lớp GridBagConstraints chỉ ra thành phần có thể được mở rộng theo hướng nằm ngang và thẳng đứng. Cú pháp sau mô tả thành phần chỉ được mở rộng theo hướng nằm ngang: gbc.fill=GridBagConstraints.HORIZNTAL; Cú pháp sau sẽ thêm vào thành phần TextArea với số dòng và số cột cần chiếm: addComponent(ta,0,2,4,1); 0 – Khởi đầu từ dòng thứ 0 2 – Khởi đầu từ dòng thứ 2 4 – ta chiếm giữ 4 dòng 1 – ta chiếm 1 cột Sử dụng cú pháp sau để bố trí các thành phần vào trong dòng và cột nào đó: gbc.gridx=col; gbc.gridy=row; Ở đây (gridx,gridy) là cột và dòng nơi mà thành phần có thể được đặt vào. Sử dụng cú pháp sau để chỉ ra số lượng các cột và dòng mà các thành phần có thể chiếm giữ: 162
  28. gbc.gridwitdh=ncol; gbc.gridheight=nrow; Ở đây, gridwidth xác định số lượng các cột mà một thành phần chiếm giữ và gridheight xác định số lượng các dòng mà một thành phần chiếm giữ. Khi một container bị thay đổi kích thước và khi khoảng trắng phụ tồn tại, các thành phần có chiều rộng lớn hơn sẽ chiếm giữ nhiều khoảng trống hơn là các thành phần có giá trị về chiều rộng nhỏ hơn. 4.5. Xử lý các sự kiện Các hệ thống GUI xử lý các tương tác người dùng với sự trợ giúp của mô hình hướng sự kiện (event-driven). Tương tác của người dùng có thể là di chuyển chuột, nhấn phím, nhả phím v.v Tất cả các thao tác này thiết lập một sự kiện của một loại nào đó. Việc xử lý những sự kiện này phụ thuộc vào ứng dụng. Abstract Windowing Toolkit (AWT) xử lý một vài sự kiện. Môi trường mà các ứng dụng này được thi hành ví dụ như trình duyệt cũng có thể xử lý các sự kiện khác. Người lập trình cũng cần phải xử lý những sự kiện nhất định và cần phải viết hàm xử lý các sự kiện đó. Ứng dụng cần đăng ký một hàm xử lý sự kiện với một đối tượng. Hàm xử lý sự kiện này sẽ được gọi bất cứ khi nào sự kiện tương ứng phát sinh. JDK1.2 làm việc theo mô hình xử lý sự kiện này. Trong quy trình này, ứng dụng cho phép bạn đăng ký các phương thức (handler), hay gọi là listener với các đối tượng. Những handler này tự động được gọi khi một sự kiện thích hợp phát sinh. Một Event Listener lắng nghe một sự kiện nào đó mà một đối tượng đã thiết lập. Mỗi event listener cung cấp các phương thức xử lý những sự kiện này. Lớp thi hành listener cần phải định nghĩa những phương thức này. Để sử dụng mô hình này, bạn làm theo các bước sau:  Cài đặt giao diện listener thích hợp. Cấu trúc như sau: public class MyApp extends Frame implements ActionListener  Xác định tất cả các thành phần tạo ra sự kiện. Các thành phần có thể là các button, label, menu item, hay window. Cho ví dụ, để đăng ký một thành phần với listener, ta có thể sử dụng: exitbtn.addActionListener(This); 163
  29.  Xác định tất cả các sự kiện được xử lý. Các sự kiện có thể là một „ActionEvent‟ nếu một button được click hay một „mouseEvent‟ nếu như chuột được kéo đi.  Thi hành các phương thức của listener và viết hàm xử lý sự kiện tương ứng với các phương thức. Bảng sau đây chỉ ra các sự kiện khác nhau và mô tả về chúng: Lớp sự kiện Mô tả ActionEvent Phát sinh khi một button được nhấn, một item trong danh sách chọn lựa được nhấn đúp (double-click) hay một menu được chọn. AdjustmentEvent Phát sinh khi một thanh scrollbar được sử dụng. ComponentEvent Phát sinh khi một thành phần được thay đổi kích thước, được di chuyển, bị ẩn hay làm cho hoạt động được. FocusEvent Phát sinh khi một thành phần mất hay nhận focus từ bàn phím. ItemEvent Phát sinh khi một mục menu được chọn hay bỏ chọn; hay khi một Checkbox hay một item trong danh sách được click. WindowEvent Phát sinh khi một cửa sổ được kích hoạt, được đóng, được mở hay thoát. TextEvent Phát sinh khi giá trị trong thành phần textfield hay textarea bị thay đổi. MouseEvent Phát sinh khi chuột di chuyển, được click, được kéo hay thả ra. KeyEvent Phát sinh khi bàn phím ấn, nhả. Bảng 4.6. các sự kiện của AWT Các giao diện cần được cài đặt để xử lý một trong số những sự kiện này là:  ActionListener  AdjustmentListener  ComponentListener  FocusListener  ItemListener 164
  30.  WindowListener  TextListener  MouseListener  MouseMotionListener  KeyListener Các giao diện định nghĩa một số phương thức để xử lý mỗi sự kiện. Những phương thức này sẽ được nạp chồng trong lớp mà cài đặt những giao diện này. Chương trình sau đây sử dụng một ActionListener để xử lý các sự kiện liên quan với một button. ActionEvent có hai phương thức:  getSource(): Để trả về nguồn của sự kiện.  toString(): Để trả về chuỗi tương đương với sự kiện. Ví dụ 4.13:Trình bày cách tính gấp đôi của một số được nhập vào. Chương trình này được thực hiện bằng cách kết hợp các phương thức của lớp, nghĩa là các phương thức xử lý sự kiện và giao diện. Việc click trên một button sẽ làm khởi động ActionEvent và gọi phương thức actionPerformed(). Nó sẽ kiểm tra button được click với sự trợ giúp của hàm getSource và trả về kết quả thích hợp. import java.awt.*; import java.awt.event.*; class EvtTest extends Frame implements ActionListener { Label lab=new Label(“Enter a number”); TextField tf1=new TextField(5); TextField tf2=new TextField(5); Button btnResult=new Button(“Double is”); Button ext=new Button(“exit”); public EvtTest(String title) { super(title); setLayout(new FlowLayout()); btnResult.addActionListener(this); ext.addActionListener(this); add(lab); 165
  31. add(tf1); add(btnResult); add(tf2); add(ext); } public void actionPerformed(ActionEvent ae) { if (ae.getSource()==btnResult) { int num=Integer.parseInt(tf1.getText())*2; tf2.setText(String.valueOf(num)); } if (ae.getSource()==ext) { System.exit(0); } } public static void main(String args[]) { EvtTest t=new EvtTest(“Event handling”); t.setSize(300,200); t.show(); } } Kết xuất chạy chương trình được như sau: 166
  32. Hình 4.16. Kết quả chạy ví dụ 4.13 Hình 4.17 sau đây chỉ ra một phần của cây phân cấp các lớp của gói event. Object java.util.EventObject Java.awt.Event ActionEvent AdjustmentEvent ComponentEvent ItemEvent ContainerEvent InputEvent FocusEvent WindowEvent KeyEvent MouseEvent Hình 4.17. Gói Event Hình sau chỉ ra thứ tự phân cấp các giao diện của các event listener. 167
  33. ActionListener AdjustmentListener E v ContainerListener e n FocusListener t L i ItemListener s t KeyListener e n MouseListener e r MouseMotionListener TextListener WindowListener Hình 4.18. Event Listener Hình sau là danh sách các listener được sử dụng cho các thành phần chỉ ra. ActionListener Button List MenuItem TextField Hình 4.19. Action Listener ItemListener Choice Checkbox List Hình 4.20. Item Listener 168
  34. WindowListener Dialog Frame Hình 4.21. Window Listener Các listener cho lớp Component được chỉ ra ở hình 4.22: Component ComponentListener FocusListener KeyListener MouseListener MouseMotionLIstener Hình 4.22. Các Component 4.6. Thực đơn Ngôn ngữ Java có một tập hợp các lớp đối tượng để tạo các menu. Có hai loại menu – pull down và pop-up. Menu làm cho ứng dụng ta xây dựng dễ sử dụng hơn. Ta chỉ có đặt duy nhất một thanh menubar trong một frame. Menubar là một thanh nằm ngang được đặt tại đỉnh của frame. Nó liệt kê các mục chọn khác nhau hay còn gọi là menu. Một menu độc lập có thể chứa các mục chọn con, các mục con này được gọi là Menu Item. Java cung cấp các Checkbox MenuItem, chúng có thể được bật hay mở, phụ thuộc vào trạng thái. Ví dụ 4.14: Minh họa cách sử dụng của menubar, menu, menuItem, và CheckboxMenuItem. import java.awt.*; import java.awt.event.*; class MyFrame extends Frame implements ActionListener, MouseListener { MenuItem exitItem; PopupMenu optionsMenu; Frame frame; 169
  35. public MyFrame() { setTitle("Menu Example"); setSize(300,200); MenuBar mbar=new MenuBar(); setMenuBar(mbar); Menu fileMenu=new Menu("File"); mbar.add(fileMenu); fileMenu.addActionListener(this); MenuItem newItem=new MenuItem("New"); fileMenu.add(newItem); MenuItem openItem=new MenuItem("Open"); fileMenu.add(openItem); fileMenu.addSeparator(); MenuItem saveItem=new MenuItem("Save"); fileMenu.add(saveItem); MenuItem saveAsItem=new MenuItem("Save As"); fileMenu.add(saveAsItem); fileMenu.addSeparator(); exitItem=new MenuItem("Exit"); fileMenu.add(exitItem); saveAsItem.addActionListener(this); Menu editMenu=new Menu("Edit"); mbar.add(editMenu); editMenu.addActionListener(this); MenuItem cutItem=new MenuItem("Cut"); editMenu.add(cutItem); MenuItem copyItem=new MenuItem("Copy"); editMenu.add(copyItem); MenuItem pasteItem=new MenuItem("Paste"); 170
  36. editMenu.add(pasteItem); editMenu.addSeparator(); Menu helpMenu=new Menu("Help"); mbar.add(helpMenu); helpMenu.addActionListener(this); MenuItem contentItem=new MenuItem("Content"); helpMenu.add(contentItem); MenuItem indexItem=new MenuItem("Index"); helpMenu.add(indexItem); Menu findMenu=new Menu("Find"); helpMenu.add(findMenu); addMouseListener(this); MenuItem nameItem=new MenuItem("Search by Name"); findMenu.add(nameItem); MenuItem cacheItem=new MenuItem("Search from cache"); findMenu.add(cacheItem); optionsMenu=new PopupMenu("Options"); editMenu.add(optionsMenu); optionsMenu.addActionListener(this); MenuItem readItem=new MenuItem("Read Only"); optionsMenu.add(readItem); optionsMenu.addSeparator(); Menu formatMenu=new Menu("Format text"); optionsMenu.add(formatMenu); this.add(optionsMenu); formatMenu.addActionListener(this); CheckboxMenuItem insertItem=new CheckboxMenuItem("Insert",true); formatMenu.add(insertItem); CheckboxMenuItem overtypeItem=new CheckboxMenuItem("Overtype",false); formatMenu.add(overtypeItem); 171
  37. } public void actionPerformed(ActionEvent ae) { if (ae.getActionCommand().equals("Exit")) { System.exit(0); } } public void mouseEntered(MouseEvent m){} public void mouseExited(MouseEvent m){} public void mouseClicked(MouseEvent m) { optionsMenu.show(this,m.getX(),m.getY()); } public void mouseReleased(MouseEvent m){} public void mousePressed(MouseEvent m){} public static void main(String[] args) { MyFrame frame=new MyFrame(); frame.show(); } } Khi thực thi chương trình trên, một màn hình với các trình đơn File, Edit và Help được hiển thị. Khi click vào mục File, sẽ thấy kết xuất sau đây: Hình 4.23. Kết quả chạy ví dụ 4.14 172
  38. Một menu có thể chứa các menu con. Khi bạn click vào trình đơn Help, 3 mục con có tên là Content, Index và Find sẽ xuất hiện. Trong trình đơn Find, có 2 mục con là Search by name và Search from Cache. Mặt khác một pop-up menu sẽ hiện ra nếu bạn nhấn chuột phải trên màn hình: Hình 4.24. Pop-up menu Các mục chọn được trình bày trên pop-up menu là Read-Only và Format text. Mục „Format text‟ có 2 mục con là Insert và Overtype. Những mục chọn con này thuộc kiểu CheckboxMenuItem. Khi bạn click vào mục chọn, nó sẽ được đánh dấu và bạn có thể thấy dấu chọn tương ứng trên mục được chọn đó. Ngôn ngữ Java cung cấp các lớp khác nhau. Những lớp này được sử dụng để tạo thanh Menubar, Menu, MenuItem và CheckboxMenuItem trong chương trình. Câu hỏi và bài tập chƣơng 4 1.Viết chương trình Java để nhập thông tin chi tiết về người sử dụng như hình sau: 2.Sửa bài tập 1 để có giao diện như sau: 173
  39. 3.Viết giao diện chương trình trò chơi puzzle như sau: 4.Sửa bài 3 để khi người sử dụng click vào nút cùng hàng hoặc cùng cột với nút không có số thì đổi chỗ nút vừa click và nút không số cho nhau. Khi người sử dụng ấn nút không cùng hàng hay không cùng cột thì hiển thông báo "Không hợp lệ" còn khi người sử dụng đã sắp xếp các nút theo thứ tự từ 1 đến 15 thì hiện ra thông báo chúc mừng. 5.Viết chương trình có menu pop-up như hình dưới đây: 174
  40. CHƢƠNG 5: JAVA APPLET VÀ SWING 5.1. Java Applet 5.1.1. Giới thiệu về Applet Applet là một chương trình Java có thể chạy trong trình duyệt web. Tất cả các Applet đều là các lớp con của lớp „Applet‟. Lớp Applet thuộc package „java.applet‟. Lớp Applet bao gồm nhiều phương thức để điều khiển quá trình thực thi của Applet. Để tạo Applet, bạn cần import hai gói sau:  java.applet  java.awt 5.1.2. Cấu trúc của một Applet Một Applet định nghĩa cấu trúc của nó từ 4 sự kiện xảy ra trong suốt quá trình thực thi. Đối với mỗi sự kiện, một phương thức được gọi một cách tự động. Các phương thức này được minh hoạ trong bảng 5.1 Điều quan trọng là không phải lúc nào Applet cũng bắt đầu từ ban đầu. Mà nó bắt đầu từ vị trí tiếp theo của quá trình thực thi trước đó. Ngoài những phương thức cơ bản này, còn có những phương thức „paint()‟ và „rẻ paint()‟. Phương thức paint() dùng để hiển thị một đường thẳng (line), text, hoặc một hình ảnh trên nền Applet. Đối số của phương thức này là đối tượng của lớp Graphics. Lớp này thuộc gói java.awt. Câu lệnh sau được dùng để import lớp Graphics: import java.awt.Graphics; Phƣơng Chức năng thức init() Được gọi trong quá trình khởi tạo applet. Trong quá trình khởi tạo, nó sẽ tạo đối tượng để cung cấp cho applet. Phương thức này được dùng để tải các hình ảnh đồ hoạ, khởi tạo các biến và tạo các đối tượng. start() Được gọi khi một applet bắt đầu thực thi. Một khi quá trình khởi tạo hoàn tất, thì applet được khởi động. Phương thức này được dùng để khởi động lại applet sau khi nó đã ngừng trước đó stop() Được gọi khi ngừng thực thi một applet. Một applet bị ngừng trước khi nó bị hủy. destroy() Được dùng để hủy một applet. Khi một applet bị hủy, thì bộ nhớ, thời gian thực thi của vi xử lý, không gian đĩa được trả về cho hệ thống. 175
  41. Bảng 5.1. Các phương thức của một applet Phương thức „repaint()‟ được dùng khi cửa sổ cần cập nhật lại. Phương thức này chỉ cần một thông số. Tham số này là đối tượng của lớp Graphics. Applet sử dụng phương thức „showStatus()‟ để hiển thị thông tin trên thanh trạng thái. Phương thức có tham số thuộc kiểu dữ liệu String. Để lấy các thông tin của applet, user có thể overide phương thức „getAppletInfo()‟ của lớp Applet. Phương thức này trả về 1 đối tượng kiểu String. Các phương thức của applet init(), start(), stop(), destroy(), và paint() được thừa kế từ một applet. Nhưng mặc định những phương thức này không thực thi một thao tác nào cả. Đây là ví dụ đơn giản của applet. Câu lệnh sau tạo một lớp có tên là „Applet1‟, lớp này sẽ kế thừa tất cả các phương thức và biến của lớp „applet‟. public class Applet1 extends Applet Phương thức init() và paint() thường được dùng để thực hiện một số hàm để khởi tạo và vẽ applet. Phương thức „g.drawString()‟ chỉ ra vị trí mà đoạn văn bản được vẽ ở đâu trên màn hình. Ví dụ 5.1: Hiển thị một chuỗi ở dòng 70 và cột 80: import java.awt.*; import java.applet.*; public class Applet1 extends Applet { int num; public void init() { num = 6; } public void paint (Graphics g) { g.drawString (“Hello to Applet. Chapter ” + num, 70, 80); showStatus (getAppletInfo()); //Hiển thị một chuỗi được trả về từ hàm getAppletInfo() trên //thanh trạng thái 176
  42. } public String getAppletInfo() //user overrides { return “Created by Aptech”; } } Sử dụng cú pháp sau để dịch một Applet: javac Applet1.java Để thực thi một applet, ta cần tạo một file HTML. File HTML này sử dụng thẻ applet. Thẻ applet này lấy tham số đầu tiên là đường dẫn của file applet. Thẻ applet có hai thuộc tính sau:  Width  Height Để truyền tham số vào applet, sử dụng param, sau đó là thuộc tính value. Sau đây là ví dụ của thẻ applet: Lúc này, ta có thể thực thi applet này bằng cách dùng trình xem applet. Đây là công cụ của JDK. Để chạy file HTML trong trình xem applet, ta gõ câu lệnh sau: appletviewer abc.html // „abc.html‟ là tên của file HTML Một tuỳ chọn khác của applet là ta thêm thẻ applet như là một dòng chú thích trong đoạn code. Lúc đó, applet được dịch và thực thi bằng cách sử dụng lệnh sau: appletviewer Applet1.java Sau đây là kết quả của chương trình trên: 177
  43. Hình 5.1. Kết quả chạy ví dụ 5.1 5.1.3. Chu trình sống của một Applet Chu trình sống của một Applet được mô tả ở sơ đồ dưới đây: Destr St oy op Creati on Starti ng Initalizati on Hình 5.2. Chu trình sống của một applet Trước tiên, applet được tạo. Bước kế tiếp là khởi tạo. Điều này xảy ra khi một applet được nạp. Quá trình này bao gồm việc tạo các đối tượng mà applet cần. Phương thức init() được định nghĩa đè để cung cấp các hành vi để khởi tạo. Một khi applet được khởi tạo, applet sẽ được khởi động. Applet có thể khởi động ngay cả khi nó đã được ngừng trước đó. Ví dụ nếu trình duyệt nhảy đến một liên kết nào đó ở trang khác, lúc đó applet sẽ bị ngừng, và được khởi động trở lại khi người sử dụng quay về trang đó. Sự khác nhau giữa quá trình khởi tạo và quá trình khởi động là một applet có thể khởi động nhiều lần, nhưng quá trình khởi tạo thì chỉ xảy ra một lần. 178
  44. Phương thức „start()‟ được overide để cung cấp các thao tác khởi động cho applet. Phương thức „stop()‟ chỉ được gọi khi user không còn ở trang đó nữa, hoặc trang đó đã được thu nhỏ lại ở dưới thanh taskbar. Kế tiếp là phương thức „destroy()‟. Phương thức này giúp applet dọn dẹp trước khi nó được giải phóng khỏi vùng nhớ, hoặc trước khi trình duyệt kết thúc. Phương thức này được dùng để hủy những luồng (thread) hay quá trình đang chạy. Phương thức „destroy()‟ khác với phương thức finalize() là phương thức destroy() chỉ dùng cho applet, trong khi finalize() là cách tổng quát để dọn dẹp applet. Phương thức paint() cũng là một phương thức quan trọng khác. Phương thức này cho phép ta hiển thị một cái gì đó trên màn hình. Có thể là text, đường thẳng, màu nền, hoặc hình ảnh. Phương thức này xảy ra nhiều lần trong suốt quá trình applet tồn tại. Phương thức này thực thi một lần sau khi applet được khởi tạo. Nó sẽ lặp đi lặp lại khi di chuyển từ cửa sổ trình duyệt sang cửa sổ khác. Nó cũng xảy ra khi cửa sổ trình duyệt thay đổi vị trí của nó trên màn hình. Phương thức „paint()‟ có một tham số. Tham số này là đối tượng của lớp Graphics. Lớp Graphics thuộc lớp java.awt, chúng ta phải import trong đoạn code của applet. Chúng ta có thể sử dụng đoạn mã sau: import java.awt.Graphics; 5.1.4. Truyền tham số cho Applet Trong chương trình sau, chúng ta sẽ truyền tham số cho applet. Thành phần nút „bNext‟ có tên được truyền như là một tham số. Phương thức „init()‟ sẽ kiểm tra tham số có tên là „mybutton‟. Sau đó, nó tạo một nút với chuỗi đó như là tên của nút. Nếu không có tham số truyền vào, nút đó có tên mặc định là „Default‟. Bây giờ chúng ta định nghĩa thẻ trong đoạn mã HTML như sau: /* */ Ví dụ 5.2: Tạo applet sử dụng truyền tham số import java.awt.*; 179
  45. import java.applet.*; /* */ public class Mybutton1 extends Applet { Button bNext; public void init() { /*getParameter returns the value of the specified pareameter in the form of a String object*/ String str = getParameter("mybutton"); //when no parameter is passed if (str==null) str = new String ("Default"); //when parameter is passed bNext = new Button(str); add (bNext); } } Sau đây là kết quả của chương trình trên: Hình 5.3. Kết quả chạy ví dụ 5.2 180
  46. Bây giờ chúng ta sẽ sử dụng lớp Graphics để vẽ các hình chẳng hạn như: đường thẳng, hình oval, và hình chữ nhật. Chúng ta sẽ học lớp Font trong các phần sau. Lớp này có thể dùng để hiển thị văn bản bằng bất cứ font nào. 5.1.5. Lớp Graphics Java cung cấp gói AWT cho phép ta vẽ các hình đồ hoạ. Lớp Graphics bao gồm tập hợp rất nhiều phương thức. Nhưng phương thức này được sử dụng để vẽ bất cứ hình nào trong các hình sau:  Oval  Rectangle  Square  Circle  Lines  Text Bạn có thể vẽ những hình này bằng bất cứ màu nào. Frame, Applet và Canvas là các môi trường để hiển thị đồ hoạ. Để vẽ bất cứ hình ảnh nào chúng ta cần phải có nền đồ hoạ (Graphical Background). Để có được một nền đồ hoạ, chúng ta gọi phương thức „getGraphics()‟ hay bất cứ phương thức nào trong các phương thức sau đây:  repaint() Được gọi khi cần vẽ lại những đối tượng đã vẽ.  update(Graphics g) Được gọi một cách tự động bởi phương thức „repaint()‟.Phương thức này sẽ xoá những đối tượng đã vẽ, và truyền nó cho đối tượng của lớp Graphics để gọi phương thức „paint()‟;  paint(Graphics g) Được gọi bởi phương thức update(). Đối tượng được truyền cho phương thức này được dùng để vẽ. Phương thức này dùng để vẽ các hình ảnh đồ hoạ khác nhau. Việc gọi phương thức paint() lặp đi lặp lại thông qua phương thức repaint() sẽ xoá đi các hình đã vẽ trước đó. Để vẽ các hình mới mà vẫn giữ lại những hình đã vẽ trước đó, chúng ta cần override lại phương thức update(). public void update (Graphics g) { paint (g); } 181
  47. Ở đây, phương thức update() sẽ không xoá những đối tượng đã vẽ, nhưng chỉ gọi phương thức paint(). Để làm được điều này, nó truyền đối tương của lớp Graphics hoặc GraphicsContext cho phương thức paint(). Ở đây, đối tượng của lớp Graphics là „g‟. a) Vẽ các chuỗi, các ký tự và các byte Để vẽ hoặc in một chuỗi, lớp Graphics cung cấp phương thức „drawString()‟. Cú pháp như sau: drawString (String str, int xCoor, int yCoor); Ba tham số là:  Chuỗi cần vẽ.  Tọa độ X trên frame, nơi chuỗi cần được vẽ.  Tọa độ Y trên frame, nơi chuỗi cần được vẽ. Để vẽ hoặc xuất các ký tự trên frame, lớp Graphics cung cấp phương thức „drawChars‟. Cú pháp như sau: drawChars (char array[], int offset, int length, int xCoor, int yCoor); Chú thích các tham số:  Mảng các ký tự.  Vị trí bắt đầu, nới các ký tự được vẽ.  Số các ký tự cần được vẽ.  Tọa độ X, nơi các ký tự cần được vẽ.  Tọa độ Y, nơi các ký tự cần được vẽ. Lớp Graphics cung cấp phương thức „drawBytes()‟ để vẽ hoặc in các byte ra frame. Cú pháp của phương thức này như sau: drawBytes (byte array[], int offset, int length, int xCoor, int yCoor); 5 tham số của phương thức trên là:  Mảng các byte.  Vị trí offset hay vị trí bắt đầu.  Số byte cần vẽ.  Tọa độ X.  Tọa độ Y. Đối với một ký tự hoặc một mảng các byte, chúng ta có thể in một phần của mảng mà thôi. Ở đây, tọa độ x và y là tọa độ tính theo dòng. Ví dụ 5.3:Minh hoạ cách vẽ chuỗi, các ký tự và các byte. import java.awt.*; public class DrawStrings extends Frame { 182
  48. public DrawStrings() { super ("Draw strings, characters, bytes"); setSize (300, 300); setVisible (true); } public void paint(Graphics g) { g.drawString ("Good Morning", 50, 50); g.drawString ("Good Afternoon", 50, 75); g.drawString ("Good Night", 50, 100); char ch[] = {'a','b','c','d','e','f'}; g.drawChars(ch,2,4,50,125); byte b[] = {100,101,102,103,104,105,106,107}; g.drawBytes(b,1,6,50,150); } public static void main (String args[]) { new DrawStrings(); } } Chương trình trên vẽ chuỗi, ký tự từ một mảng ký tự, và vẽ các byte từ mảng các byte. Bạn phải import gói java.awt để sử dụng các đối tượng đồ hoạ có sẵn trong gói này. Ta phải làm điều này vì lớp Graphics nằm trong gói này. Sau đây là kết quả của chương trình trên: 183
  49. Hình 5.4. Kết quả chạy ví dụ 5.3 b) Vẽ đƣờng thẳng (Line) và Oval Sau đây là cú pháp của các phương thức được sử dụng để vẽ đường thẳng và hình oval:  drawLine (int x1, int y1, int x2, int y2);  drawOval (int xCoor, int yCoor, int width, int height);  setColor (Color c);  fillOval (int xCoor, int yCoor, int width, int height); Phương thức „drawLine()‟ nhận các tham số sau:  Tọa độ X, nơi bắt đầu vẽ (x1).  Tọa độ Y, nơi bắt đầu vẽ (y1).  Tọa độ X, nơi kết thúc vẽ (x2).  Tọa độ Y, nơi kết thúc vẽ (y2). Phương thức này bắt đầu vẽ tại tọa độ „x1‟ và „y1‟, và kết thúc tại toa độ „x2‟ và „y2‟. Để vẽ nhưng đường thẳng có màu, chúng ta thiết lập một màu nào đó. Phương thức „setColor‟ dùng để thiết lập màu cho hình ảnh đồ hoạ. Trong chương trình này, chúng ta sử dụng câu lệnh sau để chọn màu xanh: g.setColor (Color.blue); Phương thức „drawOval()‟ nhận 4 thông số sau:  Tọa độ X.  Tọa độ Y.  Chiều rộng của hình Oval.  Chiều cao của hình Oval. Đối với hình oval rộng, thì giá trị của chiều rộng lớn hơn chiều cao, và ngược lại đối với hình oval cao. Phương thức „fillOval()‟ nhận 4 thông số, nhưng nó sẽ tô hình oval. Sử dụng phương thức setColor để đặt màu tô. g.setColor(Color.cyan); Ở đây, hình oval sẽ được tô với màu cyan. Lớp Color cung cấp các màu khác nhau mà hệ thống có hỗ trợ. 184
  50. c) Vẽ hình chữ nhật (Rectangle) và hình chữ nhật bo góc (Rounded Rectangle) Sau đây là cú pháp của các phương thức được dùng để vẽ hình chữ nhật và hình chữ nhật bo góc:  drawRect (int xCoor, int yCoor, int width, int height);  fillRect (int xCoor, int yCoor, int width, int height);  drawRoundRect (int xCoor, int yCoor, int width, int height, int arcwidth, int archeight);  fillRoundRect (int xCoor, int yCoor, int width, int height, int arcwidth, int archeight); Phương thức „drawRect()‟ được dùng để vẽ hình chữ nhật đơn giản. Phương thức này nhận 4 tham số sau:  Tọa độ X của góc trên bên trái  Tọa độ Y của góc trên bên trái  Chiều rộng của hình chữ nhật  Chiều cao của hình chữ nhật Phương thức này vẽ hình chữ nhật có chiều rộng và chiều cao cho trước, bắt đầu tại tọa độ X, Y. Chúng ta có thể thiết lập màu của hình chữ nhật. Ở đây, chúng ta chọn màu đỏ. Câu lệnh sẽ như sau: g.setColor (Color.red); Phương thức „drawRoundRect()‟ vẽ hình chữ nhật có các góc tròn. Phương thức này nhận 6 tham số, trong đó 4 tham số đầu thì giống với phương thức drawRect. Hai tham số khác là:  arcwidth của hình chữ nhật  archeight của hình chữ nhật Ở đây, „arcwidth‟ làm tròn góc trái và góc phải của hình chữ nhật. „archeight‟ làm tròn góc trên đỉnh và góc đáy của hình chữ nhật. Ví dụ, arcwidth = 20 có nghĩa là hình chữ nhật được làm tròn cạnh trái và cạnh phải mỗi cạnh 10 pixel. Tương tự, archeight = 40 sẽ tạo ra hình chữ nhật được làm tròn từ đỉnh đến đáy 20 pixel. Pixel là đơn vị đo. Nó là đơn vị nhỏ nhất trong vùng vẽ. Để tô hay vẽ hình chữ nhật và hình chữ nhật bo góc, chúng ta sử dụng phương thức „fillRect()‟ và „fillRoundRect()‟. Những phương thức này nhận các tham số giống với phương thức drawRect() và drawRoundRect(). Những phương thức này vẽ các 185
  51. hình ảnh với một màu cho trước hoặc mới màu hiện hành. Lệnh sau dùng để vẽ hình với màu xanh: g.setColor(Color.green); d) Vẽ hình chữ nhật 3D và vẽ hình cung (Arc) Sau đây là cú pháp của các phương thức dùng để vẽ hình chữ nhật 3D và hình cung:  draw3Drect (int xCoord, int yCoord, int width, int height, boolean raised);  drawArc(int xCoord, int yCoord, int width, int height, int arcwidth, int archeight);  fillArc(int xCoord, int yCoord, int width, int height, int arcwidth, int archeight); Phương thức „draw3Drect()‟ nhận 5 tham số. 4 tham số đầu thì tương tự với phương thức để vẽ hình chữ nhật. Tuy nhiên, giá trị của tham số thứ 5 quyết định là hình chữ này có 3 chiều hay không. Tham số thứ 5 có kiểu dữ liệu là boolean. Giá trị này True có nghĩa là hình chữ nhật là 3D. Phương thức „drawArc()‟ nhận 6 tham số sau:  Tọa độ x  Tọa độ y  Chiều rộng của cung được vẽ.  Chiều cao của cung được vẽ.  Góc bắt đầu.  Độ rộng của cung (góc của cung) so với góc ban đầu. Phương thức „fillArc()‟ cũng nhận 6 tham số giống như phương thức drawArc(), nhưng nó vẽ cung và tô cung với màu hiện thời. e) Vẽ hình PolyLine Chương trình sau lấy các điểm từ hai mảng để vẽ một loạt các đường thẳng. Cú pháp của phương thức này như sau:  drawPolyline (int xArray[], int yArray[], int totalPoints);  g.setFont (new Font(“Times Roman”, Font.BOLD, 15)); Phương thức „drawPolyline()‟ nhận 3 tham số sau:  Mảng lưu trữ tọa độ x của các điểm.  Mảng lưu trữ toa độ y của các điểm.  Tổng số điểm cần vẽ. 186
  52. Để vẽ các đường thẳng ta lấy các điểm từ hai mảng như sau: (array1[0], array2[0]) (array1[1], array2[1]) (array1[2], array2[2]) . Số đường thẳng vẽ được luôn nhỏ hơn số truyền vào thông số thứ 3 của phương thức drawPolyline(). Ví dụ như: totalPoints - 1 Ví dụ 5.4:Minh hoạ các vẽ polyline. import java.awt.*; class PolyLines extends Frame { int x1[] = {50, 75, 95, 115, 135}; int y1[] = {50, 30, 60, 75, 60}; int x2[] = {67, 82, 95, 120, 135}; int y2[] = {150, 130, 160, 155, 180}; public PolyLines()//constructor { super ("Poly Lines"); setSize (300, 300); setVisible (true); } public void paint (Graphics g) { g.drawPolyline (x1, y1, 5); g.setFont (new Font("Times Roman", Font.BOLD, 15)); g.drawString("Current Color is black", 100, 100); g.setColor(Color.blue); g.drawPolyline (x2, y2, 5); g.drawString ("Current Color is blue", 100, 200); } public static void main (String args[]) { new PolyLines(); 187
  53. } } Kết quả của chương trình như sau: Hình 5.5. Kết quả chạy ví dụ 5.4 f) Vẽ và tô đa giác (Polygon) Lớp Graphics cung cấp hai phương thức để vẽ đa giác. Phương thức đầu tiên nhận một đối tượng của lớp Polygon. Phương thức 2 lấy hai mảng điểm, và tổng số điểm cần vẽ. Chúng ta sẽ sử dụng phương thức 2 để vẽ đa giác. Cú pháp của drawPolygon() như sau: drawPolygon(int x[], int y[], int numPoints); Cú pháp của fillPolygon() như sau: fillPolygon (int x[], int y[], int numPoints); Chương trình dưới đây lấy các điểm từ 2 mảng để vẽ đa giác. Phương thức „drawPolygon()‟ nhận 3 tham số sau giống như phương thức drawPolyline()  Mảng lưu trữ tọa độ x của các điểm.  Mảng lưu trữ tọa độ y của các điểm.  Tổng số điểm cần vẽ. Ví dụ 5.5: Sử dụng lệnh vẽ ra các đa giác import java.awt.*; class PolyFigures extends Frame { int x1[] = {50, 25, 40, 100, 80}; 188
  54. int x2[] = {80, 30, 50, 150, 100, 170}; int y1[] = {50, 70, 120, 120, 80}; int y2[] = {150, 170, 200, 220, 240,190}; public PolyFigures() { super ("Poly figures"); setSize(300, 300); setVisible (true); } public void paint (Graphics g) { g.drawPolygon (x1, y1, 5); g.setColor (Color.cyan); g.fillPolygon (x2, y2, 6); } public static void main (String args[]) { new PolyFigures(); } } Sau đây là kết quả của chương trình trên: Hình 5.6. Kết quả chạy ví dụ 5.5 189
  55. 5.1.6. Điều khiển màu Trong Java, chúng ta điều khiển màu bằng cách dùng 3 màu chính là đỏ (red), xanh lá cây (green), xanh dương (blue). Java sử dụng mô hình màu RGB. Đối tượng của lớp Color chứa 3 số nguyên cho các tham số red, green, blue. Bảng sau trình bày giá trị có thể có của các màu đó: Thành phần Phạmvi Red 0-255 Green 0-255 Blue 0-255 Bảng 5.2. Phạm vi giá trị của các thành phần màu Sử dụng các giá trị trên để tạo ra một màu tuỳ thích. Cú pháp của hàm dựng để tạo ra một màu như sau: color (int red, int green, int blue); Bảng sau hiển thị các giá trị của các màu thường gặp: Màu Red Green Blue White 255 255 255 Light Gray 192 192 192 Gray 128 128 128 Dark Gray 64 64 64 Black 0 0 0 Pink 255 175 175 Orange 255 200 0 Yellow 255 255 0 Magenta 255 0 255 Bảng 5.3. Các giá trị RGB Các đối tượng màu khác nhau có thể được tạo bằng những giá trị này. Những đối này có thể được dùng để vẽ hoặc tô các đối tượng đồ hoạ. Ví dụ, để tạo màu hồng, ta dùng lệnh sau: color c = new Color (255, 175, 175); Ta có thể thiết lập màu bằng cách dùng lệnh sau: 190
  56. g.setColor (c); //g là đối tượng của lớp Graphics Sử dụng kết hợp các giá trị RGB để tạo ra một màu tuỳ ý. Để cho dễ hơn, lớp Color cung cấp sẵn một số màu. color.white color.black color.orange color.gray color.lightgray color.darkgray color.red color.green color.blue color.pink color.cyan color.magenta color.yellow Bảng 5.4. Các màu thường gặp Đoạn mã sau minh hoạ cách tạo một màu tuỳ ý: Color color1 = new Color (230, 140, 60); Color color4 = new Color (90, 210, 130); g.setColor (color1); int myred = color1.getRed (); int mygreen = color1.getGreen (); int myblue = color1.getBlue(); color1 = color1.darker(); color4 = color4.brighter(); 5.1.7. Điều khiển Font Java cung cấp lớp Font trong gói java.awt cho phép sử dụng các loại font khác nhau. Lớp này bao gồm một số phương thức. Để sử dụng font, chúng ta nên kiểm tra xem hệ thống có hỗ trợ hay không. Phương thức „getAllFont()‟ trả về tất cả các font mà hệ thống hỗ trợ. Trước tiên, khai báo một đối tượng của lớp GraphicsEnvironment như sau: GraphicsEnvironment ge; ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); Đối tượng này sử dụng cú pháp sau để lấy tất cả các font có trong mảng Font: Font f[] = ge.getAllFonts(); 191
  57. Phương thức getAllFont() được sử dụng ở đây. Phương thức getAllFonts() thuộc lớp GraphicsEnvironment. Đây là lớp trừu tượng, do đó ta không thể khởi tạo lớp này. để truy cập phương thức getAllFont(), chúng ta sử dụng phương thức „getLoacalGraphicsEnvironment()‟ của lớp GraphicsEnvironment. ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); Tham chiếu đến lớp này được gán cho biến ge. Biến này gọi phương thức getAllFont(). Chúng ta sử dụng các font khác nhau để hiển thị các chuỗi khác nhau. Phương thức getFont() trả về font mặc định dùng để hiển thị chuỗi, khi không có chọn font nào cả. Font defaultFont = g.getFont (); //g là đối tƣợng Graphics g.drawString (“Default Font is ”, 30, 50); Dialog là font mặc định của hệ thống. Để thay đổi font mặc định của hệ thống thành font khác, chúng ta tạo đối tượng của lớp Font. Phương thức khởi tạo của Font có 3 tham số sau:  Tên của font. Ta có thể lấy tên thông qua phương thức getFontList().  Kiểu của font. Ví dụ: Font.BOLD, Font.PLAIN, Font.ITALIC.  Kích thước font. Cú pháp sau minh hoạ những thông số trên: Font f1 = new Font (“SansSerif”, Font.ITALIC, 16); g.setFont (f1); Ba tham số được truyền ở đây là: „SanSerif‟ – tên của font, Font.BOLD – kiểu font, 14 là kích thước của font. Những thông số này tạo ra đối tượng f1. Chúng ta có thể kết hợp 2 kiểu font lại với nhau. Hãy xét ví dụ sau: Font f3 = new Font (“Monospaced”, Font.ITALIC+Font.BOLD, 20); Ở đây kiểu font của f3 vừa đậm, vừa nghiêng. 5.1.8. Lớp FontMetrics Lớp này xác định kích thước của các ký tự khác nhau thuộc các loại font khác nhau. Xác định kích thước bao gồm chiều cao (height), baseline, descent, và leading. Điều này rất cần thiết vì các ký tự khi in đều chiếm một kích thước riêng. Bạn cần tính kích thước cần thiết khi in các ký tự để tránh các ký tự đè lên nhau.  Height: chiều cao của font. 192
  58.  Baseline (Dòng cơ sở): xác định cơ sở của các ký tự (không kể phần thấp nhất của ký tự)  Ascent: khoảng cách từ đường baseline đến đỉnh của ký tự.  Descent: khoảng các từ baseline đề đáy của ký tự.  Leading: khoảng cách giữa các chữ. Ví dụ 5.6 sau minh hoạ việc sử dụng các phương thức khác nhau mà lớp FontMetrics có. Trong chương trình này, chúng ta sử dụng các phương thức khác nhau để xem xét chi tiết các loại font khác nhau. Lớp FontMetric là lớp trừu tượng. Phương thức getFontMetrics() có tham số là đối tượng của lớp Font, vì FontMetrics đi đôi với một font nào đó. FontMetrics fm = g.getFontMetrics (f1); Lệnh này tạo đối tượng fm của lớp FontMetrics, cùng với đối tượng f1. Bây giờ, chúng ta sử dụng fm để lấy chi tiết của font. Các phương thức getHeight, getAscent(), getDescent(), và getLeading() trả về chi tiết của font. Phương thức getFont() của lớp FontMetrics trả về Font mà gắn với đối tượng lớp FontMetrics. Phương thức getName() của lớp Font trả về tên Font. Ví dụ 5.6: Sử dụng các phương thức khác nhau mà lớp FontMetrics import java.awt.*; class FontMetricsUse extends Frame { public FontMetricsUse() { super ("Detail of Fonts"); setSize (400, 300); setVisible(true); } public void paint (Graphics g) { Font f1 = new Font ("Times Roman", Font.PLAIN, 22); FontMetrics fm = g.getFontMetrics (f1); String name = fm.getFont().getName(); g.drawString ("Details of Font " + name, 30, 50); 193
  59. g.drawString ("Height: " + String.valueOf (fm.getHeight()), 50, 75); g.drawString ("Ascent: " + String.valueOf (fm.getAscent()), 50, 100); g.drawString ("Descent: " + String.valueOf (fm.getDescent()), 50, 125); g.drawString ("Leading: " + String.valueOf (fm.getLeading()), 50, 150); Font f2 = new Font ("DialogInput", Font.PLAIN, 22); fm = g.getFontMetrics (f2); name = fm.getFont().getName(); g.drawString ("Details of Font " + name, 30, 175); g.drawString ("Height: " + String.valueOf (fm.getHeight()), 50, 200); g.drawString ("Ascent: " + String.valueOf (fm.getAscent()), 50, 225); g.drawString ("Descent: " + String.valueOf (fm.getDescent()), 50, 250); g.drawString ("Leading: " + String.valueOf (fm.getLeading()), 50, 275); } public static void main (String args[]) { new FontMetricsUse (); } } Kết quả của chương trình trên: Hình 5.7. Kết quả chạy ví dụ 5.6 194
  60. Ví dụ 5.7 minh hoạ cách lớp FontMetrics được sử dụng để in đoạn văn bản nhiều font, nhiều dòng. Trong chương trình này, chúng ta cần in văn bản nhiều font trên nhiều dòng. Lớp FontMetrics giúp ta xác định khoảng cách cần thiết để in một dòng văn bản cho một font nào đó. Điều này thật cần thiết, bởi vì dòng thứ 2 được in ngay sau dòng thứ nhất. Trước tiên chúng ta in msg1 sử dụng font Monospaced. Sau đó, chúng ta in msg2 sử dụng font DiaglogInput. Để làm được điều này, chúng ta cần tính khoảng cách cần thiết để in msg1. Phương thức stringWidth() của lớp FontMetrics được dùng để tính ra tổng khoảng cách cần thiết để in msg1. Khi chúng cộng thêm khoảng cách này vào biến x, chúng ta sẽ lấy được vị trí mà chúng ta bắt đầu in đoạn văn bản kế tiếp, msg2. Phương thức setFont() được dùng để thiết lập font để in văn bản. Kế đó, chúng ta in msg1 và msg2 trên các dòng khác nhau sử dụng chung 1 font Monospaced. Ở đây, chúng ta cần biết khoảng cách chiều cao của font, để in dòng kế tiếp. Phương thức getHeight() được dùng để làm điều này. Ví dụ 5.7: Minh hoạ cách lớp FontMetrics được sử dụng để in đoạn văn bản nhiều font, nhiều dòng. import java.awt.*; class MultiFontMultiLine extends Frame { public MultiFontMultiLine() { super ("Multiline Text"); setSize (450, 200); setVisible (true); } public void paint (Graphics g) { Font f1 = new Font ("MonoSpaced", Font.BOLD, 18); Font f2 = new Font ("DialogInput", Font.PLAIN, 14); int x = 20; int y = 50; String msg1 = "Java Language"; 195
  61. String msg2 = "A new approach to programming"; FontMetrics fm = g.getFontMetrics(f1); g.setFont(f1); g.drawString (msg1, x, y); x = x + fm.stringWidth(msg1); g.setFont(f2); g.drawString (msg2, x, y); g.setFont(f1); y = 100; x = 20; int height = fm.getHeight(); g.drawString (msg1, x, y); y += height; g.drawString (msg2, x, y); } public static void main (String args[]) { new MultiFontMultiLine (); } } Kết quả của chương trình trên: Hình 5.8. Kết quả chạy ví dụ 5.7 5.1.9. Chọn chế độ để vẽ Các đối tượng được vẽ bằng cách sử dụng mode vẽ. Khi một đối tượng mới được vẽ, nó sẽ đè lên các hình đã vẽ trước đây. Tương tự, khi các đối tượng được vẽ đi vẽ 196
  62. lại nhiều lần thì chúng sẽ xoá các đối tượng đã vẽ trước đó. Chỉ hiển thị nội dung của đối tượng mới. Để làm cho nội dung của và nội dung mới đều hiển thị trên cùng nền, lớp Graphics cung cấp phương thức setXORMode (Color c); Ví dụ5.8: minh hoạ tiện lợi của việc sử dụng phương thức setXORMode(). Ở đây, chúng ta sử dụng phương thức setXORMode() để tô các hình đồ hoạ khác nhau, mà không đè lên các hình khác. Kết quả là, khi sử dụng mode XOR thì hiển nhiên là tất cả các hình đều hiển thị đầy đủ. Điều này có nghĩa là các hình mới không đè lên các hình cũ. Thay vào đó, phần chung giữa các hình sẽ được hiển thị thành một màu khác. Nhưng khi không sử dụng mode XOR, hình mới hoàn toàn che khuất những hình trước đó. import java.awt.*; class PaintMode extends Frame { public PaintMode() { super ("Paint Mode"); setSize (300, 300); setVisible (true); } public void paint (Graphics g) { g.setPaintMode (); g.setColor (Color.blue); g.fillRect (50,50,40, 30); g.setColor (Color.pink); g.fillOval (70, 65, 30, 60); g.setColor (Color.cyan); g.fillRoundRect (90, 80, 70, 50, 20, 30); g.setColor (Color.blue); g.fillRect (50, 150, 40, 30); g.setXORMode (Color.yellow); g.fillOval (70, 165, 30, 60); 197
  63. g.setXORMode (Color.magenta); g.fillRoundRect (90, 180, 60, 40, 50, 20); } public static void main (String args[]) { new PaintMode(); } } Kết quả của chương trình trên: Hình 5.9. Kết quả chạy ví dụ 5.8 5.2. Java Swing 5.2.1 Giới thiệu về Swing Phần trên chúng ta đã xây dựng giao diện người dùng với các lớp AWT. Bây giờ chúng ta sẽ xem xét khái niệm Swing. Swing là một bộ các lớp cung cấp các thành phần mạnh và linh hoạt hơn AWT. Ngoài các thành phần quen thuộc như nút nhấn, hộp kiểm tra và nhãn, Swing còn hỗ trợ các bảng thẻ, bảng cuộn, cây và bảng. Chính các thành phần quen thuộc như các nút nhấn có nhiều khả năng hơn trong Swing. Ví dụ, một nút nhấn có thể có hình ảnh và một chuỗi văn bản tương ứng với nó. Hình ảnh này có thể được thay đổi khi trạng thái của nút nhấn thay đổi. Không giống các thành phần AWT, các thành phần Swing không thi hành bằng đoạn mã đặc tả nền. Thay vì thế chúng được viết hoàn toàn bằng Java, vì thế là độc lập với hệ thống. Các lớp và giao diện trong Swing quan trọng, và chương này trình bày một vài khía cạnh tổng quát. Swing là một lãnh vực mà bạn muốn tìm hiểu nhiều hơn theo cách riêng của bạn. Các lớp thành phần Swing được sử dụng trong cuốn sách này được trình bày như sau: 198
  64. Lớp Diễn giải AbstractButton Tách các phân lớp cho các nút nhấn Swing ButtonGroup Tóm lược một bộ các nút nhấn loại trừ lẫn nhau ButtonGroup Tóm lược một bộ các nút nhấn loại trừ lẫn nhau ImageIcon Tóm lược một biểu tượng JApplet Phiên bản Swing của Applet Jbutton Lớp nút nhấn Swing JcheckBox Lớp hộp kiểm tra Swing JComboBox Tóm lược một combo box (sự kết hợp của danh sách thả xuống và văn bản ) JLabel Phiên bản Swing của nhãn JRadioButton Phiên bảng Swing của radio JScrollPane Tóm lược một cửa sổ cuộn JTabbedPane Tóm lược một cửa số thẻ Jtable Tóm lược bộ điều khiển bảng cơ sở JTextField Phiên bảng swing của văn bản JTree Tóm lược sự điều khiển cây cơ sở Bảng 5.5. Các lớp thành phần Swing Các lớp quan hệ Swing được lưu trong javax.swing và các gói của nó như javax.swing.tree. Nhiều lớp quan hệ Swing và giao diện tồn tại mà không được xem xét trong chương này. Phần còn lại của chương trình này xem xét các thành phần Swing khác nhau và minh họa chúng thông qua các applet. 5.2.2. Các biểu tƣợng và nhãn Trong Swing, biểu tượng được tóm lược bởi lớp ImageIcon, vẽ một biểu tượng từ một hình ảnh. Hai construstor của nó như sau:  ImageIcon (String filename)  ImageIcon (URL url) Hàm thứ nhất sử dụng hình ảnh trong tập tin tên là filename. Hàm thứ hai sử dụng hình ảnh trong resource được nhận biết bằng url. Hàm Diễn giải 199
  65. Int getIconHeight() Trả về số pixel là chiều cao của biểu tượng Int getIconWeight() Trả về số pixel là chiều rộng của biểu tượng Int paintIcon(Component Vẽ biểu tượng tại vị trí x,y trên đồ họa g. comp. Graphics g, int x, thông tin về thao tác vẽ được cung cấp trong int y) comp. Bảng 5.6. Các hàm sử dụng của JLabel Các nhãn Swing là trường hợp của lớp JLabel, thừa kế từ Jcomponent. Nó có thể hiển thị văn bản và hay một biểu tượng. Các constructor của nó như sau:  JLabel(Icon i)  JLabel (String s)  JLabel (String s, int align) Ở đây, s và i là văn bản và biểu tượng sử dụng cho nhãn. Thông số align là LEFT, RIGHT hay CENTER. Các hằng số này được định nghĩa trong giao diện SwingConstants, cùng với những cái khác sử dụng bởi các lớp Swing. Biểu tượng và văn bản tương ứng với nhãn có thể đọc và ghi bằng các hàm sau:  Icon getIcon()  String getText()  Void setIcon(Icon i)  Void setText(String s) Ở đây, i và s là biểu tượng và văn bản. Ví dụ 5.9: Tạo ra một nhãn sử dụng Swing import javax.awt.*; import javax.swing.*; public class JLabelDemo extends Japplet { public void init() { Container contentPane= getContentPane(); ImageIcon ii=new ImageIcon("france.gif"); Jlabel jl=new Jlabel ("France",ii, Jlabel,CENTER); contentPane.add(ji); } } 5.2.3. Các trƣờng văn bản Các trường văn bản Swing được tóm lược bởi lớp JTextCompnent, thừa kế từ JComponent. Nó cung cấp các chức năng chung cho các thành phần văn bản Swing. 200
  66. Một lớp con của nó là JTextField, cho phép bạn chỉnh sửa một dòng của văn bản. Các constructor của nó là:  JTextField()  JTextField(int cols)  JTextField(String s, int cols)  JTextField(String s) Ở đây, s là chuỗi đang được xét, và cols là số cột trong trường văn bản. Ví dụ 5.10 minh họa cách tạo một trường văn bản. Applet bắt đầu bằng cách lấy content pane của nó, và sau đó một sắp xếp được ấn định như layout manager của nó. Kế tiếp một đối tượng JTextField được tạo và được gắn vào content pane. import javax.awt.*; import javax.swing.*; public class JTextFieldDemo extends JApplet { JTextField jtf; public void init() { Container contentPane= getContentPane(); contentPane.setLayout(new FlowLayout()); jtf=new JTextField(15); contentPane.add(jtf); } } 5.2.4. Nút nhấn Các nút nhấn Swing cung cấp các đặc tính mà không tìm thấy trong lớp Button được định nghĩa bởi AWT. Ví dụ, bạn có thể kết hợp một biểu tượng với một nút nhấn Swing. Nút nhấn Swing là phân lớp của lớp AbtractButton, là lớp thừa kế từ Jcomonent. AbtractButton, gồm nhiều hàm cho phép bạn điều khiển hoạt động của các nút nhấn, hộp kiểm tra, và nút radio. Ví dụ, bạn có thể định nghĩa các biểu tượng khác nhau để hiển thị cho các thành phần khi nó được kích hoạt, được nhấn hay được chọn. Biểu tượng khác có thể được sử dụng như một biểu tượng "di động qua", nó được hiển thị khi chuột di chuyển đến thành phần đó. Sau đây là các hàm điều khiển các hoạt động này:  void setDisabledIcon(Icon di)  void setPressadIcon(Icon pi)  void setSelectedIcon(Icon si)  void setRolloverIcon(Icon ri) 201
  67. Ở đây, di, pi, si và ri là các biểu tượng được sử dụng cho các điều kiện khác nhau. Văn bản tương ứng với một nút nhấn có thể đọc hay ghi thông qua các hàm sau:  String getText()  void setText(String s) Ở đây, s là văn bản ứng với nút nhấn. Phân lớp cụ thể của AbstractButton tạo ra các sự kiện khi chúng được nhấn. Bộ theo dõi ghi và tháo bỏ các sự kiện của chúng thông qua các hàm sau: void addActionListener(ActionListener al) void removeActionListener(ActionListener al) Ở đây, al là bộ theo dõi hoạt động. AbstractButotn là lớp con của nút nhấn, hộp kiểm tra và nút radio. Mỗi trường hợp sẽ được xem xét kế tiếp. 5.2.5. Lớp JButton Lớp JButton cung cấp chức năng của một nút nhấn. JButton cho phép một biểu tượng, một chuỗi, hay cả hai tương ứng với nút nhấn. Các constructor của nó là:  JButton(Icon i)  JButton(String s)  JButton(String s, Icon i) Ở đây s và i là chuỗi và biểu tượng sử dụng cho nút nhấn. 5.2.6. Hộp kiểm tra Lớp JcheckBox cung cấp chức năng của một hộp kiểm tra, là một lớp con cụ thể của AbstractButton. Các constructor của nó là: JCheckBox(Icon i)  JCheckBox(Icon I, boolean state)  JCheckBox(String s)  JCheckBox(String s, boolean state)  JCheckBox(String s, Icon i)  JCheckBox(String s, Icon I, boolean state) Ở đây, i là biểu tượng của nút nhấn. Văn bản được xác định bởi s. nếu state là true, lúc đầu hộp kiểm tra sẽ được chọn. Ngược lại, nó sẽ không được chọn. Trang thái của hộp kiểm tra có thể thay đổi thông qua hàm sau: void setSelacted(boolean state) 202
  68. Ở đây state là true nếu hộp kiểm tra sẽ được đánh dấu. 5.2.7. Radio Button Radio button được cung cấp bởi lớp JradioButton, là sự thi hành cụ thể của AbstractButton. Các constructor của nó là: JRadioButton(Icon i)  JRadioButton(Icon I, boolean state)  JRadioButton(String s)  JRadioButton(String s boolean state)  JRadioButton(String s, Icon i)  JRadioButton(String s, Icon I, boolean state) Ở đây i là biểu tượng của button. Văn bản được xác định bởi s. Nếu state là true, lúc đầu button được chọn. Ngược lại nó không được chọn. Nút radio được xác định như một nhóm. Chỉ một button trong nhóm có thể được chọn vào một thời điểm. Ví dụ, nếu người dùng nhấn một nút radio trong một nhóm, bất kỳ nút nào trong nhóm đó đã được chọn trước cũng tự động không được chọn nữa. Lớp ButtonGroup tạo một nhóm button. Constructor mặc định của nó cần cho mục đích này. Sau đó các thành phần được thêm vào nhóm button thông qua hàm sau: void add(AbstractButton ab) Ở đây ab là một tham chiếu đến button được thêm vào nhóm. 5.2.8. ComboBox Swing cung cấp một ComboBox (một sự kết hợp của một trường văn bản và một danh sách thả xuống) thông qua lớp JComboBox, thừa kế từ Jcomponent. Một ComboBox bình thường hiển thị một danh sách thả xuống để cho phép người dùng chọn một thực thể khác. Bạn có thể nhập sự lựa chọn của bạn vào trường văn bản. Hai constructor của JComboBox là: JComboBox() , JComboBox (Vector v) Ở đây, v là một vector khởi tạo combo box. Các mục được thêm vào danh sách chọn thông qua hàm addItem(), cách thức như sau: void add Item(Object obj) Ở đây obj là đối tượng thêm vào combo box 5.2.9. Tabbed Pane Một Tabbed Pane là một thành phần được hiển thị như một nhóm các folders trong một tập tin cabinet. Mỗi folder có một tên. Khi người dùng chọn một folder, nội 203
  69. dung của nó sẽ được kích hoạt. Chỉ một folder có thể được chọn tại một thời điểm. Tabbed pane được sử dụng để xác định cấu hình các phần. Tabbed pane được tóm lược bởi lớp JTabbedPane, thừa kế từ Jcomponent. Chúng ta sẽ sử dụng constructor mặc định của nó. Tab được định nghĩa thông qua hàm sau: void addtab(String str, Component comp) Ở đây str là tên của tab, và comp là thành phần sẽ được thêm vào tab. Một Jpanel hay một phân lớp của nó được thêm vào. Thủ tục chung để sử dụng một Tabbed pane trong một applet gồm các bước sau: Tạo một đối tượng JTabbedPane Gọi hàm addTab() để thêm một tab vào panel. (Các thông số đến hàm này định nghĩa tựa đề của tab và thành phần của nó). Lặp lại bước hai cho mỗi tab Thêm tabbed pane cho content pane của applet. 5.2.10. Scroll Pane Scroll pane là một thành hiển thị một vùng hình chữ nhật trong một thành phần có thể nhìn thấy. Các thanh cuộn dọc và ngang có thể được cung cấp nếu cần thiết. Scroll pane thi hành trong Swing bởi lớp JScrollPane, là lớp mở rộng Jcomponent. Các constructor của nó là:  JScrollPane(Component comp)  JScrollPane(int vsb, int hsb)  JScrollPane(Component comp, int vsb, int hsb) Ở đây comp là thành phần được thêm vào scroll pane. Vsb và hsb là các hằng số kiểu int được định nghĩa khi thanh cuộn ngang và dọc của scroll pane này hiển thị. Các trường hợp của các hằng số này được trình bày như sau: Hằng số Diễn giải HORIZONTAL_SCROLLBAR_ALWAYS Luôn cung cấp thanh cuộn ngang HORIZONTAL_SCROLLBAR_AS_NEEDED Cung cấp thanh cuộn ngang, nếu cần VERTICAL_SCROLLBER_ALWAYS Luôn cung cấp thanh cuộn dọc 204
  70. HORIZONTAL_SCROLLBAR_AS_NEEDED Cung cấp thanh cuộn dọc, nếu cần Bảng 5.7. Các hằng số Sau đây là các bước mà bạn sẽ sử dụng một Jscroll pane trong một applet: 1. Tạo một đối tượng JComponent. 2. Tạo một đối tượng JScrollPane. Các thông số của constructor xác định thành phần và sự kiểm soát của thanh cuộn doc và ngang. 3. Thêm JscrollPane vào ContentPane của applet này. 5.2.11. Cây Cây là một thành phần miêu tả một sự hiển thị có thứ tự của dữ liệu. Người dùng có thể mở rộng hay thu nhỏ các cây con riêng lẻ trong các hiển thị này. Cây thực hiện trong Swing bởi lớp JTree là một lớp mở rộng của JComponent. Các constructor của nó là:  JTree(Hashtable ht)  JTree(Object obj[])  JTree(TreeNode tn)  JTree(Vector v) Hàm thứ nhất tạo một cây trong đó mỗi thành phần của bảng băm là một nút con. Trong hàm thứ hai mỗi thành phần của mảng obj là một nút con. Trong hàm thứ ba nút cây tn là gốc của cây. Hàm cuối cùng sử dụng các thành phần của vector v như các nút con. Một đối tượng JTree phát sinh các sự kiện khi một nút được mở rộng hay thu nhỏ. Các hàm addTreeExpansionListener() và removeTreeExpansion Listener () cho phép bộ theo dõi ghi nhận và tháo bỏ sự khai báo này. Dạng của các hàm này như sau:  void addTreeExpansionListener(TreeExpansionListener tel)  void removeTreeExpansionListener(TreeExpansionListener tel) Ở đây tel là đối tượng theo dõi. Hàm getPathForLocation() sử dụng để di chuyển chuột dựa vào một vị trí đặc biệt của cây theo một hướng đi của cây. Dạng của nó như sau: TreePath getPathForLocation(int x, int y) Ở đây x và y là các tọa độ mà chuột sẽ nhấp vào. Giá trị trả về là một đối tượng TreePath, đối tượng này tóm lược thông tin về nút cây được chọn bởi người dùng. 205
  71. Lớp TreePath tóm lược thông tin về đường đi đến một nút đặc biệt trong một cây. Nó cung cấp vài constructor và hàm. Trong cuốn sách này, chỉ có hàm toString() được sử dụng. Nó trả về một chuỗi tương ứng với đường đi của cây.Giao diện TreeNode trình bày các hàm lấy thông tin về một nút cây. Ví dụ, có thể lấy được một tham chiếu đến nút cha hay bảng danh sách các nút con. Giao diện MutableTreeNode mở rộng TreeNode. Nó trình bày các hàm mà có thể chèn và bỏ các nút con hay thay đổi nút cha. Lớp DefaultMutableTreeNode thực hiện giao diện MutableTreeNode. Nó miêu tả một nút của cây. Một constructor của nó như sau: defaultMutableTreeNode(Object obj) Ở đây obj là đối tượng chứa nút cây này. Nút cây mới không có cha hay con. Ðể tạo một thứ tự cho các nút cây, hàm add() của DefaultMutableTreeNode có thể được sử dụng. Dạng của nó như sau: void add(MutableTreeNode child) Ở đây child là một nút cây được thêm vào như con của nút hiện hành. Các sự kiện mở rộng cây được trình bày bởi lớp TreeExpansionEvent trong javax.swing.event. Hàm getPath() của lớp này trả về một đối tượng TreePath, đối tượng này trình bày đường đi đến nút đã sẽ được thay đổi. Dạng của nó như sau: TreePath getPath() Giao diện TreeExpansionListener cung cấp hai hàm sau:  void treeCollapsed (TreeExpansionEvenr tee)  void treeExpandeed(TreeExpansionEvenr tee) Ở đây tee là sự kiện mở rộng cây. Hàm thứ nhất được gọi khi một cây con bị giấu đi, và hàm thứ hai được gọi khi cây con được hiện thị. Sau đây là các bước tạo một cây trong một applet: 1. Tạo một đối tượng JTree. 2. Tạo một đối tượng JScrollPane. Các thông số đến constructor xác định cây và sự kiểm soát thanh cuộn dọc và ngang) 3. Thêm cây vào scroll pane. 4. Thêm scroll pane vào content pane của applet. 206
  72. 5.2.12. Bảng Một bảng là một thành phần hiển thị các dòng và các cột của dữ liệu. Bạn có thể kéo con trỏ trên ranh giới cột để thay đổi kích thước các cột. Bạn cũng có thể kéo một cột đến một vị trí mới. Bảng thực hiện bởi lớp JTable, là lớp mở rộng Jcomponent. Một constructor của nó là: JTable(Object data[][], Object colHeads[]) Ở đây data là một mảng hai chiều của thông tin sẽ được hiển thị và colHeads là một mảng một chiều lưu trên một cột. Sau đây là các bước tạo một bảng trong một applet: 1. Tạo một đối tượng JTable. 2. Tạo một đối tượng JScrollPane (các thông số của constructor xác định bảng và sự kiểm soát thanh cuộn dọc và ngang) 3. Thêm bảng vào scroll pane. 4. Thêm scroll pane vào content pane vào applet Ví dụ 5.11:sau minh hoạ cách tạo và sử dụng một bảng. Content pane của đối tượng JApplet được hiện hành và khung layout được ấn định như layout manager của nó. Bảng này có ba cột. Một mảng hai chiều của chuỗi được tạo cho các ô của bảng. Bạn có thể xem xét mỗi phần tử trong mảng là một mảng của ba chuỗi. Các mảng này được chuyển cho constructor JTable. Bảng này được thêm vào scroll pane và sau đó scroll pane được thêm vào content pane. import javax.swing.*; import javax.swing.event.*; import javax.swing.tree.*; import javax.accessibility.*; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.util.*; import java.io.*; import java.applet.*; import java.net.*; public class TreeDemo extends DemoModule { 207
  73. public static void main(String[] args) { TreeDemo demo = new TreeDemo(null); demo.mainImpl(); } public TreeDemo(SwingSet2 swingset) { // Set the title for this demo, and an icon used to represent this super(swingset, "TreeDemo", "toolbar/JTree.gif"); getDemoPanel().add(createTree(), BorderLayout.CENTER); } public JScrollPane createTree() { DefaultMutableTreeNode top = new DefaultMutableTreeNode(getString("TreeDemo.music")); DefaultMutableTreeNode catagory = null ; DefaultMutableTreeNode artist = null; DefaultMutableTreeNode record = null; // open tree data URL = getClass().getResource("/resources/tree.txt"); try { // convert url to buffered string InputStream is = url.openStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader reader = new BufferedReader(isr); String line = reader.readLine(); while(line != null) { // System.out.println("reading in: ->" + line + "<-"); char linetype = line.charAt(0); switch(linetype) { case 'C': catagory= new DefaultMutableTreeNode(line.substring(2)); top.add(catagory); break; 208
  74. case 'A': if(catagory != null) { catagory.add(artist = new DefaultMutableTreeNode(line.substring(2))); } break; case 'R': if(artist != null) { artist.add(record = new DefaultMutableTreeNode(line.substring(2))); } break; case 'S': if(record != null) { record.add(new DefaultMutableTreeNode(line.substring(2))); } break; default: break; } line = reader.readLine(); } } catch (IOException e) { } JTree tree = new JTree(top) { public Insets getInsets() { return new Insets(5,5,5,5); } }; return new JScrollPane(tree); } } 209
  75. Câu hỏi và bài tập chƣơng 5 1.Cho lớp GiaiThua và lớp Java Swing GiaiThua_UI gồm các thuộc tính, phương thức và giao diện như hình sau: a) Viết chương trình tạo lớp GiaiThua trong đó: - Thuộc tính n là số cần tính. - Các phương thức gồm: các setters/getters cho các thuộc tính, Các Constructor, phương thức KiemTra() đùng để kiểm tra giá trị nhập vào n có phải là một số nguyên dương không, TinhGT() để tính n!. b) Tạo lớp GiaiThua_UI sử dụng các đối tượng của Java Swing theo mẫu. c) Sử dụng lớp GiaiThua đã tạo để thực hiện các tính toán cho lớp GiaiThua_UI sao cho khi người dùng kích chuột vào nút Tính n! thì tính n! và hiển thị kết quảra màn hình nếu n nguyên dương, trong trường hợp còn lại thì thông báo lỗi. 2. Cho lớp PhepTinh và lớp Swing PhepTinh_UI gồm các thuộc tính, phương thức và giao diện mô tả như hình sau: a) Viết chương trình tạo lớp PhepTinh trong đó: 210
  76. -Các thuộc tính ToanHang1, ToanHang2 là các toán hạng, ToanTu là các phép toán +, -, *, /. - Các phương thức gồm: các setters/getters cho các thuộc tính, các Constructor, thức KiemTra() đùng để kiểm tra giá trị nhập vào có phải là một số nguyên không và TinhToan() để tính giá trị của biểu thức. b) Tạo lớp PhepTinh_UI sử dụng các đối tượng của Java Swing theo mẫu ở hình trên c) Sử dụng lớp PhepTinh đã tạo để tính toán cho lớp PhepTinh_UI sao cho khi người dùng kích chuột vào nút “Tính toán”thì tính giá trị rồi hiển thị kết quả, nếu giá trị các toán hạng đều là số nguyên, trong các trường hợp còn lại thông báo lỗi ra màn hình. 3. Cho lớp PhanSo và lớp Java Swing PhanSo_UI gồm các thuộc tính, phương thức và giao diện như mô tả ở hìnhsau: a) Viết chương trình tạo lớp PhanSo trong đó: - Các thuộc tính TuSo, MauSo là tử số và mẫu số của phân số. - Các phương thứcgồm: các setters/getters cho các thuộc tính, các Constructor, KiemTra() đùng để kiểm tra giá trị nhập vào có phải là một số nguyên không, RutGon() đùng để tính và trả về phân số rút gọn của phân số đã cho và TinhToan() để tính giá trị phân số. b) Tạo lớp PhanSo_UI sử dụng các đối tượng của Java Swing theo mẫu. c) Sử dụng lớp PhanSo đã tạo để tính toán cho lớp PhanSo_UI sao cho: 211
  77. - Khi người dùng kích chuột vào nút “Rút gọn” thì tìm phân số rút gọn rồi hiển thị kết quả, nếu các giá trị tử số và mẫu số nhập vào là các số nguyên, trong các trường hợp còn lại thì thông báo lỗi. - Khi người dùng kích chuột vào nút “Tính giá trị của phân số” tính giá trị và hiển thị kết quả ra màn hình nếu các giá trị tử số và mẫu số nhập vào là các số nguyên, trong các trường hợp còn lại thông báo lỗi ra màn hình. 4. Cho lớp PhuongTrinhBacNhat và lớp Java Swing PhuongTrinhBacNhat_UI gồm các thuộc tính, phương thức và giao diện như mô tả ở hình sau: a) Viết chương trình tạo lớp PhuongTrinhBacNhat trong đó: - Các thuộc tính a, b là các hệ số của phương trình. - Các phương thức gồm: các setters/getters cho các thuộc tính, các Constructor, KiemTra() đùng để kiểm tra giá trị nhập vào có phải là một số nguyên không, toString() đùng để trả về dạng chuỗi của phương trình bậc nhất dạng ax+b=0, và GiaiPT() để biện luận nghiệm của phương trình bậc nhất. b) Tạo lớp PhuongTrinhBacNhat_UI sử dụng các đối tượng của Java Swing theo mẫu. c) Sử dụng lớp PhuongTrinhBacNhat đã tạo để thực hiện các tính toán cho lớp PhuongTrinhBacNhat_UI gồm: - Nút “Phương trình” dùng để trả lại dạng chuỗi của phương trình bậc nhất, nếu dữ liệu nhập vào a và b là các số nguyên, trong các trường hợp còn lại thông báo lỗi ra màn hình. 212
  78. - Nút “Giải phương trình” dùng để tính nghiệm của phương trình tương ứng nếu dữ liệu nhập vào a, b là các số nguyên và a khác 0, trong các trường hợp còn lại thông báo lỗi ra màn hình. 5. Cho lớp PhuongTrinhBac2 và lớp Swing PhuongTrinhBac2_UI gồm các thuộc tính, phương thức và giao diện như mô tả trong hình sau: a) Viết chương trình tạo lớp PhuongTrinhBac2 trong đó - Các thuộc tính a, b, c là các hệ số của phương trình bậc 2 ax2+bx+c=0 - Các phương thức gồm: các setters/getters cho các thuộc tính, các Constructor, phương thức KiemTra() đùng để kiểm tra giá trị nhập vào có phải là một số nguyên không, toString() đùng để trả về dạng chuỗi của phương trình bậc nhất dạng ax^2+bx+c=0, GiaiPT() để giải phương trình bậc hai. b) Tạo lớp PhuongTrinhBac2_UI sử dụng các đối tượng của Java Swing theo mẫu. c) Sử dụng lớp PhuongTrinhBac2 đã tạo để thực hiện các tính toán cho lớp PhuongTrinhBac2_UI gồm: - Nút “Phương trình” dùng để tính và trả lại dạng chuỗi của phương trình bậc 2, nếu dữ liệu nhập vào đúng, ngược lại sẽ thông báo lỗi - Nút “Giải phương trình” dùng để tính nghiệm của phương trình bậc 2 tương ứng, nếu dữ liệu nhập vào đúng, ngược lại sẽ thông báo lỗi. 6. Cho lớp SinhVien và lớp Swing SinhVien_UI gồm các thuộc tính, phương thức và giao diện như mô tả ở hình sau: 213
  79. a) Viết chương trình tạo lớp SinhVien trong đó: - Các thuộc tính gồm: MaSV là mã sinh viên, HoTen là họ tên, NgaySinh là ngày sinh, GioiTinh là giới tính, DiaChi là địa chỉ của sinh viên. - Các phương thức gồm: các setters/getters cho các thuộc tính, các Constructor. b)Tạo lớp SinhVien_UI sử dụng các đối tượng của Java AWT theo mẫu. c) Sử dụng lớp SinhVien đã tạo để viết chương trình cho các nút của lớp SinhVien_UI gồm: - Nút “Thêm sinh viên” dùng để thêm một sinh viên vào danh sách, mã sinh viên sẽ được tự động thêm vào danh sách mã sinh viên bên trái. - Khi người dùng lựa chọn một mã sinh viên trong danh sách thông tin của sinh viên đó được lấy ra các control bên phải để sửa đổi. - Khi người dùng kích vào “Sửa sinh viên” thì thông tin sửa sẽ được ghi lại. 7. Cho lớp GiaoVien và lớp Swing GiaoVien_UI gồm các thuộc tính, phương thức và giao diện như mô tả ở hình sau: 214
  80. a) Viết chương trình tạo lớp GiaoVien trong đó: - Các thuộc tính gồm:MaGV là mã giáo viên, HoTen là họ tên, Diachi là địa chỉ, HeSoLuong là hệ số lương của giáo viên. - Các phương thức gồm: các setters/getters cho các thuộc tính, các Constructor. b)Tạo lớp giao diện GiaoVien_UI sử dụng các đối tượng của Java AWT theo mẫu. c)Sử dụng lớp GiaoVien đã tạo để viết chương trình cho các nút của lớp GiaoVien_UI gồm: - Nút “Thêm giáo viên” dùng để thêm một giáo viên vào danh sách, danh sách giáo viên sẽ được hiển thị ở bảng phía dưới. - Khi người dùng lựa chọn giáo viên trong danh sách thông tin của giáo viên đó được lấy ra các control bên trên để xóa. - Khi người dùng kích vào “Xóa” sẽ xóa đi giáo viên được lựa chọn đó. 8.Cho lớp Sach và lớp Swing Sach_UI gồm các thuộc tính, phương thức và giao diện mô tả như hình sau: a) Viết chương trình tạo lớp Sach trong đó: - Các thuộc tính gồm: Ten là tên sách, Tacgia là tác giả, gia là giá, nam là năm xuất bản cuốn sách. - Các phương thức gồm: các setters/getters cho các thuộc tính và các Constructor. b) Tạo lớp giao diện Sach_UI sử dụng các đối tượng của Java AWT theo mẫu. c)Sử dụng lớp Sach đã tạo để viết chương trình cho các nút của lớp Sach_UI gồm: 215
  81. - Nút “Thêm mới” dùng để thêm sách vào danh sách, danh sách sẽ được hiển thị ở bảng phía dưới. -Khi người dùng lựa chọn sách trong danh sách thông tin của sách đó được lấy ra các control bên trên để xóa. - Khi người dùng kích vào “Xóa” sẽ xóa đi sách được lựa chọn. 9. Cho lớp XeMay và lớp Swing XeMay_UI gồm các thuộc tính, phương thức, giao diện như hình sau: a) Viết chương trình tạo lớp XeMay trong đó: - Các thuộc tính gồm: Biensolà biển số xe, TenXe là tên xe, Mau là màu của xe, HangSX là hãng sản xuất xe. - Các phương thức bao gồm: các setters/getters cho các thuộc tính, cácConstructor. b)Tạo lớp giao diện XeMay_UI sử dụng các đối tượng của Java AWT theo mẫu. c)Sử dụng lớp XeMay đã tạo để viết chương trình cho các nút của lớp XeMay_UI gồm: - Nút “Thêm mới” dùng để thêm xe máy vào danh sách, danh sách sẽ được hiển thị ở bảng phía dưới. -Khi người dùng lựa chọn xe máy trong danh sách thông tin của xe máy đó được lấy ra các control bên trên để sửa. - Khi người dùng sửa thông tin kích vào “Sửa” sẽ sửa thông tin của xe được lựa chọn. 216
  82. 10. Cho lớp HocSinh và lớp Swing HocSinh _UI gồm các thuộc tính, phương thức, giao diện như hình sau: a) Viết chương trình tạo lớp HocSinh trong đó: - Các thuộc tính gồm: Mahslà Mã học sinh, Hoten là Họ tên, DiemToan là điểm môn toán, DiemViet là điểm môn viết. - Các phương thức bao gồm: các setters/getters cho các thuộc tính, cácConstructor. b)Tạo lớp giao diện HocSinh_UI sử dụng các đối tượng của Java AWT theo mẫu. c)Sử dụng lớp HocSinh đã tạo để viết chương trình cho các nút của lớp HocSinh_UI gồm: - Nút “Thêm mới” dùng để thêm học sinh vào danh sách, danh sách sẽ được hiển thị ở bảng phía dưới. -Khi người dùng lựa chọn học sinh trong danh sách thông tin của học sinh đó được lấy ra các control bên trên. - Khi người dùng kích vào “Xóa” sẽ xóa học sinh được lựa chọn khỏi danh sách. 11.Cho lớp KhachHang và lớp Swing KhachHang _UI gồm các thuộc tính, phương thức, giao diện như hình sau: 217
  83. a) Viết chương trình tạo lớp KhachHang trong đó: - Các thuộc tính gồm: Makhlà Mã khách hàng, Tenkh là Họ tên khách hàng, Email là địa chỉ email, Sotaikhoan là số tài khoản của khách. - Các phương thức bao gồm: các setters/getters cho các thuộc tính, cácConstructor. b)Tạo lớp giao diện KhachHang_UI sử dụng các đối tượng của Java AWT theo mẫu. c)Sử dụng lớp KhachHang đã tạo để viết chương trình cho các nút của lớp KhachHang_UI gồm: - Nút “Thêm mới” dùng để thêm khách hàng vào danh sách, danh sách tên khách hàng được hiển thị ở bên trái. - Khi người dùng lựa chọn tên khách hàng trong danh sách, thông tin của khách hàng đó được lấy ra các control bên phải. - Khi người dùng kích vào “Xóa”, sẽ xóa khách hàng được lựa chọn khỏi danh sách. 12. Cho lớp TongChan và lớp Swing TongChan_UI gồm các thuộc tính, phương thức, giao diện như hình sau: 218
  84. a) Viết chương trình tạo lớp TongChan trong đó: - Thuộc tính nlà một số nguyên. - Các phương thức bao gồm: các setters/getters cho các thuộc tính, cácConstructor, KiemTra() dùng để kiểm tra một chuỗi có phải là số nguyên dương không, TinhTong() dùng để tính tổng s = 1/2+1/4+ +1/2*n. b)Tạo lớp giao diện TongChan_UI sử dụng các đối tượng của Java AWT theo mẫu. c)Sử dụng lớp TongChan đã tạo để viết chương trình cho các nút của lớp TongChan_UI sao cho khi người dùng kích vào nút Tính tổng 1/2+1/4 + +1/2*n thì sẽ tính tông sau đó hiển thị kết quả ra màn hình, nếu giá trị nhập vào là số nguyên dương, ngược lại sẽ thông báo lỗi. 13. Sử dụng Java Awt và Java Applet viết chương trình vẽ hình mặt người theo mẫu ở hình sau: 14. Sử dụng Java Awt và Java Applet viết chương trình vẽ chữ JAVA theo mẫu ở hình sau: 219
  85. 15. Sử dụng Java Awt và Java Applet viết chương trình vẽ hình người theo mẫu ở hình sau: 16. Sử dụng Java Awt và Java Applet viết chương trình vẽ hình người tuyết theo mẫu ở hình sau: 17. Sử dụng Java Awt và Java Applet viết chương trình vẽ tranh bốn mùa theo mẫu ở hình sau: 220
  86. 18.Sử dụng Java Awt, Java Applet, và ActionListener viết chương trình sao cho mỗi lần người dùng vào nút “Ve Bong” sẽ vẽ ra màn hình quả bóng có kích thước, màu sắc và vị trí thay đổi ngẫu nhiên ví dụ mẫu ở hình sau: 19.Sử dụng Java Awt, Java Applet, và ActionListener viết chương trình sao cho mỗi lần người dùng vào nút “Tao bong” sẽ vẽ ra màn hình 1000 quả bóng có kích thước, màu sắc và vị trí thay đổi ngẫu nhiên ví dụ mẫu ở hình sau: 221
  87. 20. Sử dụng Java Awt và Java Applet viết chương trình vẽ biểu đồ hình tròn theo mẫu ở hình sau: 21. Sử dụng Java Awt, Java Applet và các sự kiện chuột MouseListener viết chương trình vẽ 4 hình vuông theo mẫu sau, sao cho khi kích chuột lên hình vuông nào đó thì nó sẽ đổi màu ngẫu nhiên. 22. Sử dụng Java Awt, Java Applet và các sự kiện chuột MouseListener viết chương trình vẽ hình mặt người theo mẫu ở hình dưới, sao cho khi kích chuộtlên Smile thì hình mặt người là smile (Nền màu vàng và miệng cười), kích chuột lên Sad thì hình sad(Nền màu nâu, miệng méo). 222
  88. 23. Sử dụng Java Awt, Java Applet vẽ ra màn hình 20 dòng chữ Java tạo thành vòng tròn có màu biến thiên dần từ đỏ sang xanh theo mẫu ở hình sau: 24. Sử dụng Java Awt, Java Applet vẽ bia bắn (là các đường tròn đồng tâm màu đỏ và trắng) theo mẫu ở hình sau: 25. Sử dụng Java Awt, Java Applet, viết chương trình vẽ các đoạn thẳng màu xanh trên nền trắng quanh một tâm cố định theo mẫu ở hình sau: 26. Sử dụng Java Awt, Java Applet, viết chương trình vẽ các hình chữ nhật màu hồng trên nền trắng theo mẫu ở hình sau: 223
  89. 27. Sử dụng Java Awt, Java Applet, viết chương trình vẽ bàn cờ vua các ô màu đỏ và đen theo mẫu ở hình sau: CHƢƠNG 6: LẬP TRÌNH ĐA LUỒNG 6.1. Giới thiệu về lập trình luồng Luồng là một thuộc tính duy nhất của Java. Nó là đơn vị nhỏ nhất của đoạn mã có thể thi hành được để thực hiện một công việc nhất định. Ngôn ngữ Java, máy ảo Java cả hai đều là các hệ thống phân luồng 6.2. Luồng và đa luồng Java hỗ trợ đa luồng, nó có khả năng làm việc với nhiều luồng. Một ứng dụng có thể bao hàm nhiều luồng. Mỗi luồng được gán một công việc cụ thể, chúng được thực thi đồng thời với các luồng khác. Đa luồng làm giảm tối đa thời gian nhàn rỗi của hệ thống. Điều này cho phép bạn viết các chương trình có hiệu quả cao với sự tận dụng tối đa CPU. Mỗi phần của 224
  90. chương trình được gọi một luồng, mỗi luồng định nghĩa một cách thực hiện. Đây là một trường hợp đặc biệt của đa nhiệm. Trong đa nhiệm, nhiều chương trình chạy đồng thời, mỗi chương trình có ít nhất một luồng trong nó. Một bộ vi xử lý thực thi tất cả các chương trình này. Qua đó chương trình được thực thi như là đồng thời, trên thực tế bộ vi xử lý chuyển qua chuyển lại giữa các chương trình. 6.3. Tạo và quản lý luồng Khi các chương trình Java được thực thi, luồng chính đã đang được thực hiện. Hai yếu tố quan trong luồng chính (main) là:  Các luồng con sẽ được tạo ra từ nó.  Nó là luồng cuối cùng kết thúc việc thực hiện. Ngay khi luồng chính ngừng thực thi, chương trình bị chấm dứ t. Cho dù luồng chính được tạo ra một cách tự động với chương trình thực thi, nó có thể được điều khiển thông qua một đối tượng luồng. Các luồng có thể được tạo ra từ hai cách:  Khai báo lớp là lớp con của lớp Thread, và phương thức run() của lớp Thread cần được định nghĩa đè. Ví dụ 6.1: Tạo một lớp con của lớp Thread class Mydemo extends Thread { public void run() { //thực thi } }  Khai báo lớp cài đặt giao diện Runnable. Rồi thì định nghĩa phương thức run(). class MyDemo implements Runnable { public void run() { //thực thi } 225