25/05/2018, 07:30

Xây dựng ứng dụng Window

Applications < > Applets standalone application : sử dụng tài nguyên chỉ của một computer. networked application : sử dụng các tài nguyên trên mạng. distributed application : ứng dụng gồm nhiều ...

Applications < > Applets

standaloneapplication : sử dụng tài nguyên chỉ của một computer. networkedapplication : sử dụng các tài nguyên trên mạng.

distributedapplication : ứng dụng gồm nhiều đối tượng chạy trên nhiều máy tính khác nhau.

Ưng dụng độc lập lại gồm hai loại :

window applications sử dụng hệ thống window : Microsoft Windows, Macintosh OS, Motif, OS/2.

console applications : tương tác với NSD qua dòng lệnh, giống như các chương trình DOS hay UNIX shells.

Thiết kế chương trình Window

Hai bước cơ sở :

- bố trí (laying out) GUI

- Cung cấp các chức năng qua giao diện.

+ Bước thứ nhất - look and feel- của một chương trình window.

  • xác định các đăc trưng cơ bản của window : kích thước, tiêu đề, màu background, foreground và layout.
  • thêm thanh chọn chính, các mục chọn.
  • Các GUI controls để gắn vào window.

+ Phần xử lí sự kiện, đáp ứng các tương tác của NSD.

- Điều khiển bằng sự kiện - event driven- vòng lặp sự kiện.

Với Java chúng ta không phải xây dưng vòng lặp sự kiện và nhận dạng các sự kiện ở mức thấp.

- Phương thức mà Java sẽ tự động gọi khi có sự kiện.

- Tham số là một đối tượng kiểu sự kiện (kế thừa từ lớp EventObject).

- Dùng đối tượng này để nhận các thông tin chi tiết về sự kiện ta quan tâm.

Trên cơ sở đó thực hiện xử lí tương ứng.

Khung chương trình Window

import java.awt.*;

import java.awt.event.*;

...

public class <cửaSổChính> extends Frame {

// khai báo, khởi trị các biến.

public static void main(String args[]){

// Khơi tạo đối tượng cửa sổ chính

<cửaSổChính> app = new <cửaSổChính>(..);

...

}

// Constructor

public <cửaSổChính>(...) {

// các lệnh khởi trị

// đăng kí obj xử lí sự kiện

addWindowListener(<xửLíSựKiệnWindow>);

...

show();

}

public void paint(Graphics g) {

// vẽ nội dung hiển thị

}

class <xửLíSựKiệnWindow> extends WindowAdapter // phương thức xử lí sự kiện

public void phươngThứcXửLí(WindowEvent e) {... }

}

}

}

Chương trình hello window

Chỉ quan tâm đến một sự kiện là nhấn nút đóng cửa sổ.

Phương thức để xử lí là windowClosing(WindowEvent e).

Hello Windows!

Chương trình HelloWindows

import java.awt.*;

import java.awt.event.*;

public class HelloWindows extends Frame {

public static void main(String args[]){

HelloWindows app = new HelloWindows();

}

public HelloWindows() {

super("Hello Windows!");

setSize(200,200);

addWindowListener(new HelloWindows.WindowEventHandler());

show();

}

public void paint(Graphics g) {

g.drawString("Hello Windows!",50,90);

}

class WindowEventHandler extends WindowAdapter {

public void windowClosing(WindowEvent e){

System.exit(0);

}

}

}

Giải thích hoạt động.

Frame và Graphics là nền tảng để xây dựng ứng dụng window.

Frame để tạo cửa sổ chính của ứng dụng - main windows

Graphics để vẽ cập nhật lại hiển thị màn hình.

WindowAdapter để xử lí sự kiện.

Công thức viết chương trình window :

HelloWindows <- Frame.

main() : entry point của chương trình.

show() : hiển thị cửa sổ

paint() : mỗi khi có thay đổi trong hiển thị window.

Xử lý sự kiện

WindowAdapter -> WindowEventHandler.

addWindowListener() gắn các sự kiện của cửa sổ mới tạo ra với đối tượng WindowEventHandler.

WindowEvent là sự kiện window chuẩn : thu nhỏ, phóng to, đóng.

Nội dung xử lí : không làm gì cả, mà kết thúc chưong trình bằng exit().

Window

Window khung cơ bản

-> Frame -> main window

-> Dialog = hộp thoại.

show() hiển thị window (mặc định là invisible) chỉ hiển thị khi show() toFront(), toBack() : vị trí tương đối của windows đang xét đối với frame window.

dispose() : giải phóng các tài nguyên, huỷ đối tượng Window.

getWarningString() : nhận các cảnh báo.

Layout mặc định của Window là BorderLayout.

Frame

Frame : để xây dựng cửa sổ chính cho một ứng dụng.

Cho phép tạo window icon, cursor, menu bar, title.

Có các hằng để ấn định các kiểu cursors khác nhau trong frame.

Lớp Cursor.

2 constructors :

- mặc định, không tham số, tạo một frame window không tiêu đề.

- có tham số là một String - tiêu đề của cửa sổ.

phương thức : get, set tiêu đề, icon image, menu bar, gỡ bỏ menu bar, có thể co giãn hay không..

Dialog

Window -> Dialog = hộp thoại.

Modal phải được đóng trước khi trả điều khiển về cho nơi gọi nó.

non-modal

FileDialog

Dialog -> FileDialog = hộp thoại hỗ trợ cho việc chọn các tệp

Thao tác input, output.

mode LOAD hay SAVE.

Mở và đóng Windows

Khởi đầu và kết thúc của mọi chương trình window.

Lớp Frame cho phép triển khai các thao tác cơ bản này.

Để mở một ứng dụng window :

- tạo một đối tượng Frame

- gọi show().

Để đóng một ứng dụng window :

- hoàn thành mọi thủ tục cần thiết để kết thúc chương trình, cần -

- gọi dispose() của lớp Window hay System.exit().

Nhiều phương thức điều khiển cách hiển thị window.

setBackground(), setForeground().

setFont() : font mặc định của window.

setTitle() : thay đổi tiêu đề.

setMenuBar() : gắn menu bar vào window

setResizable() : bật tắt khả năng co giãn window

setIconImage() : thay đổi (minimized) icon của cửa sổ.

Nhiều thành phần GUI khác

Mô hình event delegation.

Lớp Adapter : các đối tượng lắng nghe các sự kiện thay cho các đối tượng khác.

Đối tượng nguồn - thành phần GUI - sinh ra sự kiện,

Đối tượng listener thuộc lớp adapter, có giao diện để lắng nghe sự kiện

Có các phương thức (của đối tượng nguồn) để listener đăng kí để lắng nghe các sự kiện thay cho nó.

Ví dụ : Button.

Nhấn Button = ActionEvent

xử lí việc nhấn button :

- Lắng nghe = ActionListener -> cần tạo một đôí tượng

ActionListener.

- addActionListener() của lớp Button gắn ActionListener vào button đang xét.

Khuôn mẫu chung

[_X_]Event -> [_X_]Listener -> add[_X_]Listener

EventObject là lớp đỉnh trên cây sự kiện.

Lớp này có biến (trường) source để chỉ ra đối tượng là nguồn gốc của sự kiện.

getSource() là phương thức để lấy đối tượng này

toString() : sự kiện -> String thông tin về sự kiện.

EventObject -> AWTEvent : các sự kiện AWT.

AWTEvent -> event.

Các loại sự kiện

  • ActionEvent--phát sinh do hành động của NSD, nhấn chuột, chọn mục chọn ...
  • AdjustmentEvent-- phát sinh do cuộn thanh cuộn.
  • ComponentEvent-- phát sinh do thay đổi vị trí của các thành phần window - di chuyển, co giãn ... hoặc gõ phím hay các thao tác chuột khác.
  • InputMethodEvent-- phát sinh do thay đổi trong text gõ vào khi dùng một phương thức input.
  • InvocationEvent--phát sinh do các phương thức invokeLater() và invokeAndWait() của lớp java.awt.EventQueue.
  • ItemEvent--phát sinh do thay đổi trạng thái của một component, chẳng hạn chọn một mục trong danh sách.
  • TextEvent--phát sinh do các sự kiện liên quan đến text, ví dụ thay đổi trong một text field.

Lớp ComponentEvent được phát triển thành các lớp sau:

  • FocusEvent--phát sinh do thay đổi status of a component's input focus
  • InputEvent-- để dẫn xuất ra KeyEvent và MouseEvent nhằm vào các sự kiện phát sinh khi gõ phím hoặc thao tác chuột.
  • ContainerEvent--phát sinh khi có thêm hay gỡ bỏ một thành phần trong container.
  • PaintEvent--phát sinh khi painting/repainting một cửa sổ.
  • WindowEvent--phát sinh khi mở, đóng, thu gọn (minimizing) một cửa sổ.

Các sự kiện được định hướng tới các đối tượng chuyên biệt lắng nghe sự kiện đó.

Các đối tượng này có các EventListener.

Được phát triển thành :

  • ActionListener--cài đặt trong các đối tượng xử lí sự kiện ActionEvent.
  • AdjustmentListener-- cài đặt trong các đối tượng sử lí sự kiện AdjustmentEvent.
  • ComponentListener-- cài đặt trong các đối tượng sử lí sự kiện ComponentEvent.
  • ContainerListener-- cài đặt trong các đối tượng sử lí sự kiện ContainerEvent.
  • EventQueueListener-- cài đặt trong các đối tượng monitor hàng đợi sự kiện hệ thống.
  • FocusListener-- cài đặt trong các đối tượng sử lí sự kiện FocusEvent.
  • InputMethodListener-- cài đặt trong các đối tượng sử lí sự kiện InputMehtodEvent.
  • ItemListener-- cài đặt trong các đối tượng sử lí sự kiện ItemEvent.
  • KeyListener-- cài đặt trong các đối tượng sử lí sự kiện KeyEvent.
  • MouseListener-- cài đặt trong các đối tượng sử lí sự kiện MouseEvent về nhấn chuột.
  • MouseMotionListener-- cài đặt trong các đối tượng sử lí sự kiện MouseEvent về di chuyển chuột.
  • TextListener-- cài đặt trong các đối tượng sử lí sự kiện TextEvent.
  • WindowListener-- cài đặt trong các đối tượng sử lí sự kiện WindowEvent.

java.awt.event package cung cấp lớp adapter dùng để cài đặt các event listener interfaces.

Các lớp này dùng để dẫn xuất và viết đè lên các phương thức xử lí sự kiện cụ thể mà ta quan tâm.

Các lớp adapter của java.awt.event như sau:

  • ComponentAdapter-- cài đặt ComponentListener interface và xử lí sự kiện ComponentEvent.
  • ContainerAdapter--cài đặt ContainerListener interface và sử lí ContainerEvent.
  • FocusAdapter--cài đặt FocusListener interface và xử lí FocusEvent.
  • KeyAdapter-- cài đặt KeyListener interface và xử lí KeyEvent.
  • MouseAdapter--cài đặt MouseListener interface và xử lí MouseEvent về nhấn chuột.
  • MouseMotionAdapter--cài đặt MouseListener interface và xử lí MouseEvent về di chuyển chuột.
  • WindowAdapter--cài đặt WindowListener interface và xử lí WindowEvent.

Các lớp phục vụ xây dựng bảng chọn.

Tạo và xử lí bảng chon buông xuống.

MenuComponent là tổ tiên của mọi lớp liên quan đến bảng chọn.

MenuComponent có các phương thức getFont(), setFont().

MenuBar, MenuItem : có nhiều phương thức để tạo và sử dụng bảng chọn.

MenuItem -> CheckboxMenuItem : các mục chọn có thể bật tắt. MenuItem -> Menu : để thể hiện một loại MenuItem, gắn cho menuBar. (nghĩa là lại mở ra một bảng chọn buông xuống).

MenuItem là lớp mẹ của lớp Menu. Điều này cho phép một menu cũng là một menu item và do đó có thể xây dựng bảng chọn nhiều cấp lồng nhau.

Menu -> PopupMenu : bảng chọn nổi lên bên trong một component.

MenuShortcut : để tạo phím tắt ứng với các mục chọn.

Frame có thể có một và chỉ một MenuBar,

Gắn vào bằng setMenuBar().

Một đối tượng Menu chứa các MenuItem ( normal, CheckboxMenuItem , hoặc là một (đối tượng) Menu khác).

ý nghĩa của Kí tự đầu tiên

+ Mục chọn cho phép (enabled) và được đánh dấu chọn.
# Mục chọn không cho phép (disabled) và được đánh dấu.
- Mục chọn cho phép (enabled) và chưa được đánh dấu chọn. Nếu chỉ có dấu - thì là một đường kẻ ngang.
= Mục chọn không cho phép (disabled) và không được đánh dấu.
~ Mục chọn bình thường không cho phép (disabled).

Hai lớp hỗ trợ thêm - MyMenu, MyMenuBar

Lớp MyMenu.

package ju.ch09;

import java.awt.*;

import java.awt.event.*;

public class MyMenu extends Menu {

public MyMenu(Object labels[],ActionListener al,ItemListener il) {

super((String)labels[0]);

String menuName = (String) labels[0];

char firstMenuChar = menuName.charAt(0);

if(firstMenuChar == '~' || firstMenuChar =='!'){

setLabel(menuName.substring(1));

if(firstMenuChar == '~') setEnabled(false);

}

for(int i=1;i<labels.length;++i) {

if(labels[i] instanceof String){

if("-".equals(labels[i])) addSeparator();

else{

String label = (String)labels[i];

char firstChar = label.charAt(0);

switch(firstChar){

case '+':

CheckboxMenuItem checkboxItem = new CheckboxMenuItem(label.substring(1));

checkboxItem.setState(true);

add(checkboxItem);

checkboxItem.addItemListener(il);

break;

case '#':

checkboxItem = new CheckboxMenuItem(label.substring(1));

checkboxItem.setState(true);

checkboxItem.setEnabled(false);

add(checkboxItem);

checkboxItem.addItemListener(il);

break;

case '-':

checkboxItem = new CheckboxMenuItem(label.substring(1));

checkboxItem.setState(false);

add(checkboxItem);

checkboxItem.addItemListener(il);

break;

case '=':

checkboxItem = new CheckboxMenuItem(label.substring(1));

checkboxItem.setState(false);

checkboxItem.setEnabled(false);

add(checkboxItem);

checkboxItem.addItemListener(il);

break;

case '~':

MenuItem menuItem = new MenuItem(label.substring(1));

menuItem.setEnabled(false);

add(menuItem);

menuItem.addActionListener(al);

break;

case '!':

menuItem = new MenuItem(label.substring(1));

add(menuItem);

menuItem.addActionListener(al);

break;

default:

menuItem = new MenuItem(label);

add(menuItem);

menuItem.addActionListener(al);

}

}

}else{

add(new MyMenu((Object[])labels[i],al,il));

}

}

}

public MenuItem getItem(String menuItem) {

int numItems = getItemCount();

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

if(menuItem.equals(getItem(i).getLabel())) return getItem(i);

return null;

}

}

Constructor của MyMenu có tham số là : mảng nhãn mục chọn, các đối tượng ActionListener, ItemListener.

Các phương thức :

getItem() để lấy mục chọn khi biết nhãn. Nó sử dụng các phưong thức getItemCount(), getItem() của lớp Menu để lấy các mục chọn và getLabel() của lớp MenuItem để tìm khi biết nhãn.

Bảng chọn File với các mục New, Open, vạch ngang, Exit.

String fileMenuLabels[] = {"File","New","Open","-","Exit"};

// EventHandler must implement the ActionListener and ItemListener interfaces.

EventHandler eh = new EventHandler();

MyMenu fileMenu = new MyMenu(fileLabelMenus,eh,eh);

Phần tử đầu tiên phaỉ là một String, làm nhãn của menu chính. Các String tiếp theo là nhãn các mục chọn , vạch ngang, hay lại là mảng (lồng ở mức trong) gồm các nhãn của menu thứ cấp.

Dưới đây là ví dụ menu nhiều cấp

String goMenuLabels[] = {"Go","Beginning","End","Previous","Next"};

String editMenuLabels[] = {"Edit","Copy","Cut","-","Paste","-", goMenuLabels};

// EventHandler must implement the ActionListener and ItemListener interfaces.

EventHandler eh = new EventHandler();

MyMenu editLabel = new MyMenu(editMenuLabels,eh,eh);

Lớp MyMenuBar

MyMenuBar ; để tạo menu bar.

MyMenuBar sử dụng mảng các mảng nhãn để tạo thanh chọn chính với nhiều bảng chọn buông xuống.

Thanh chọn chính với các mục File, Edit, Help

Mỗi mục lại buông xuống một bảng các mục chọn.

String menuBarLabels[] = {

{"File","New","Open","-","~Save As","-","Exit"};

{"Edit","Copy","Cut","-","~Paste"};

{"Help","Index"};

};

// EventHandler must implement the ActionListener and ItemListener interfaces.

EventHandler eh = new EventHandler();

MyMenuBar menuBar = new MyMenuBar(menuBarLabels,eh,eh);

Lưu ý rằng các mục chọn Save As và Paste ban đầu là disabled.

Lớp MyMenuBar.

package ju.ch09;

import java.awt.*;

import java.awt.event.*;

public class MyMenuBar extends MenuBar {

public MyMenuBar(Object labels[][],ActionListener al,

ItemListener il) {

super();

for(int i=0;i<labels.length;++i)

add(new MyMenu(labels[i],al,il));

}

public MyMenu getMenu(String menuName) {

int numMenus = getMenuCount();

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

if(menuName.equals(getMenu(i).getLabel())) return((MyMenu)getMenu(i));

return null;

}

}

Constructor của MyMenuBar duyệt lần lượt mảng vòng ngoài, chuyển các phần tử của mảng này (lại là một mảng) cho constructor của MyMenu.

Sau đó add() để thêm đối tượng MyMenu vào MyMenuBar.

Chương trình MenuApp

Tạo một cửa sổ có thanh chọn chính với các bảng chọn buông xuống.

import java.awt.*;

import java.awt.event.*;

import ju.ch09.MyMenu;

import ju.ch09.MyMenuBar;

public class MenuApp extends Frame {

MyMenuBar menuBar;

MenuApp.EventHandler eh = new MenuApp.EventHandler();

public static void main(String args[]){

MenuApp app = new MenuApp();

}

public MenuApp() {

super("Menu Madness");

setup();

setSize(400,400);

addWindowListener(eh);

show();

}

void setup() {

setBackground(Color.white);

setupMenuBar();

}

void setupMenuBar(){

String gotoMenu[] = {"Go To","Beginning","End","-","Line Number"};

Object menuItems[][] = {

{"File","New","Open","-","~Save","~Save As","-","Exit"},

{"Edit","Copy","Cut","-","~Paste"},

{"Search","Find","~Find Next","~Find Previous","-", gotoMenu},

{"View","-Hex","+Line Number","+Column Number"},

{"Help","About Menu Madness"},

};

menuBar = new MyMenuBar(menuItems,eh,eh);

setMenuBar(menuBar);

}

class EventHandler extends WindowAdapter implements ActionListener, ItemListener {

public void actionPerformed(ActionEvent e){

String selection=e.getActionCommand();

if("Exit".equals(selection)){

System.exit(0);

}else if("New".equals(selection) || "Open".equals(selection)){

menuBar.getMenu("File").getItem("Save").setEnabled(true);

menuBar.getMenu("File").getItem("Save As").setEnabled(true);

}else if("Copy".equals(selection) || "Cut".equals(selection)){

menuBar.getMenu("Edit").getItem("Paste").setEnabled(true);

}else if("Find".equals(selection)){

menuBar.getMenu("Search").getItem("Find Next").setEnabled(true);

menuBar.getMenu("Search").getItem("Find Previous").setEnabled(true);

}else if("About Menu Madness".equals(selection)){

menuBar.getMenu("Help").setEnabled(false);

}

}

public void itemStateChanged(ItemEvent e){

}

public void windowClosing(WindowEvent e){

System.exit(0);

}

}

}

Bảng chọn Popup

Menu -> PopupMenu

show() : hiển thị. ( trong Component nào, toạ độ x, y ).

MouseEvent , ComponentEvent.

isPopupTrigger() của lớp MouseEvent : xác định sự kiện chuột là gắn với popup menu hay không.

getComponent() của ComponentEvent sẽ cho biết thành phần nơi sự kiện chuột xảy ra.

Dialog : cửa sổ hiển thị độc lập, không có menu bar.

Nó có thể là modal : hiển thị thông tin và nhận trả lời của NSD thông qua thao tác nhấn chuột.

Lớp MessageDialog

Kiểu hộp thoại thường dùng nhất.

MessageDialog CLASS.

package ju.ch09;

import java.awt.*;

import java.awt.event.*;

public class MessageDialog extends Dialog {

public MessageDialog(Frame parent,String title,boolean modal,String text[],

String buttons[], WindowListener wh, ActionListener bh) {

super(parent,title,modal);

int textLines = text.length;

int numButtons = buttons.length;

Panel textPanel = new Panel();

Panel buttonPanel = new Panel();

textPanel.setLayout(new GridLayout(textLines,1));

for(int i=0;i<textLines;++i) textPanel.add(new Label(text[i]));

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

Button b = new Button(buttons[i]);

b.addActionListener(bh);

buttonPanel.add(b);

}

add("North",textPanel);

add("South",buttonPanel);

setBackground(Color.lightGray);

setForeground(Color.black);

pack();

addWindowListener(wh);

}

}

Chương trình MessageApp.

Các hộp thoại điển hình trong một chương trình window.

Chương trình MessageApp.

import java.awt.*;

import java.awt.event.*;

import ju.ch09.MyMenu;

import ju.ch09.MyMenuBar;

import ju.ch09.MessageDialog;

public class MessageApp extends Frame {

MyMenuBar menuBar;

MessageDialog dialog;

DialogHandler dh = new DialogHandler();

public static void main(String args[]){

MessageApp app = new MessageApp();

}

public MessageApp() {

super("MessageApp");

setup();

setSize(400,400);

addWindowListener(new WindowEventHandler());

show();

}

void setup() {

Object menuItems[][] = {

{"File","Exit"},

{"View","Information","Confirmation","Selection"},

};

MenuItemHandler mih = new MenuItemHandler();

menuBar = new MyMenuBar(menuItems,mih,mih);

setMenuBar(menuBar);

}

class MenuItemHandler implements ActionListener, ItemListener {

public void actionPerformed(ActionEvent ev){

String s=ev.getActionCommand();

if(s=="Exit"){

System.exit(0);

}else if(s=="Information"){

String text[] = {"Don't look now, but your shoelace is untied."};

String buttons[] = {"OK"};

dialog = new MessageDialog(MessageApp.this,"Information",false,

text,buttons,dh,dh);

dialog.setLocation(75,75);

dialog.show();

}else if(s=="Confirmation"){

String text[] = {"Do you really want to do this?"};

String buttons[] = {"Yes","No","Cancel"};

dialog = new MessageDialog(MessageApp.this,"Confirmation",false,

text,buttons,dh,dh);

dialog.setLocation(75,75);

dialog.show();

}else if(s=="Selection"){

String text[] = {"What direction do you want to go?",

"North: cold", "South: warm", "East: humid", "West: arid"};

String buttons[] = {"North","South","East","West"};

dialog = new MessageDialog(MessageApp.this,"Selection",false,

text,buttons,dh,dh);

dialog.setLocation(75,75);

dialog.show();

}

}

public void itemStateChanged(ItemEvent e){

}

}

class WindowEventHandler extends WindowAdapter {

public void windowClosing(WindowEvent e){

System.exit(0);

}

}

class DialogHandler extends WindowAdapter implements ActionListener {

public void windowClosing(WindowEvent e){

MessageApp.this.show();

dialog.dispose();

}

public void actionPerformed(ActionEvent e){

MessageApp.this.show();

dialog.dispose();

}

}

}

0