Thiết kế GUI cho chương trình

1. Tạo khung chứa cửa sổ chương trình

Thông thường để tạo cửa sổ chính cho chương trình ứng dụng ta tiến hành các bước:

  • Tạo đối tượng Frame
  • Xác định kích thước của Frame
  • Thể hiện Frame trên màn hình

Ví dụ:

import java.awt. *;

class FrameDemo

{

public static void main(String args[])

{

// Tạo đối tượng khung chứaFrame Frame fr = new Frame(“My First Window”) ;

// Xác định kích thước, vị trí của Frame fr.setBounds(0, 0, 640, 480);

// Hiển thị Frame

}

}

2. Tạo hệ thống thực đơn

Đối với thư viện awt, để xây dựng hệ thống thực đơn cho chương trình ứng dụng chúng ta có thể dùng các lớp MenuBar, Menu, MenuItem, MenuShortcut.

Ví dụ: Tạo hệ thống thực đơn cho chương trình Calculator

import java.awt. *; import java.awt.event. *; class Calculator {

public static void main(String[] args)

{
}

private static void createMenu()

{

// Tao Frame ung dung final Frame fr = new Frame(); fr.setLayout(new BorderLayout());

// Tao cac menu bar

MenuBar menu = new MenuBar();

Menu menuFile = new Menu(“Edit”);

Menultem copyltem = newMenuItem(“Copy Ctrl+C”); Menultempasteltem = newMenuItem(“Paste Ctrl+V”); menuFile. add(copy!tem); menuFile. add(pasteItem);

Menu menuHelp = newMenu(“Help”);

Menultem hTopicItem = newMenuItem(“Help Topics”); Menultem hAboutItem = new MenuItem(“About Calculator”);

menuHelp. add(h TopicItem); menuHelp. addSeparator(); menuHelp. add(hA boutItem); menu. add(menuFile); menu. add(menuHelp);

fr. setMenuBar(menu); fr.setBounds(100, 100, 300, 200); fr. setTitle(“Calculator “);

//fr. setResizable (false); fr.setVisible(true);

// xử lý biến sự kiện đóng cửa số ứng dụng. fr. addWindowListener(

new WindowAdapter()

{

public void windowClosing(WindowEvent e) {

System.exit(O);

}

});

}

}

Kết quả thực thi chương trình:

3. Gắn Component vào khung chứa

Để gắn một thành phần, một đối tượng component vào một cửa số (khung chứa) chúng ta dùng phương thức add của đối tượng khung chứa container.

Ví dụ:

import java.awt. *; class AddDemo

public static void main(String args[])

{

// Tạo đối tượng khung chứaFrame Frame fr = new Frame(“AddDemo App”); // Tạo đối tượng Component

Button buttũk = new Button(“OK”);

// Gắn đối tượng nút nhấn vào khung chứa fr.add(buttOk);

// Xác định kích thước, vị trí của Frame fr.setSize(100, 100);

// Hiển thị Frame fr.setVisible(true);

}

}

Kết quả thực thi:

4. Trình bày các Component trong khung chứa

Như chúng ta đã biết khung chứa container nhận các đối tượng từ bên ngoài đưa vào và nó phải biết làm thế nào để tổ chức sắp      xếp     “chỗ       ở”    cho các            đối       tượng  đó.       Mỗi      đối                  tượng khung chứa đều có một bộ quản lý chịu trách nhiệm thực hiện công việc đấy đó là bộ quản lý trình bày (Layout Manager). Chúng ta sẽ tìm hiểu chi tiết về các kiểu trình bày của thư viện AWT

Interface LayoutManager định nghĩa giao tiếp cho những lớp biết được làm thế nào để trình bày những trong những containers

4.1.FlowLayout

public class FlowLayout extends Object

implements LavoutManager, Serializable

Đối với một container trình bày theo kiểu FlowLayout thì:

  • Các component gắn vào được sắp xếp theo thứ tự từ trái sang phải và từ trên xuống dưới.
  • Các component có kích thước như mong muố n.
  • Nếu chiều rộng của Container không đủ chỗ cho các component thì chúng tự động tạo ra một dòng mới.
  • FlowLayout thường được dùng để để sắp xếp các button trong 1
  • Chúng ta có thể điều chỉnh khoảng cách giữa các component.

4.2. BorderLayout

public class BorderLayout extends Object

implements LayoutManager2, Serializable

Đối với một container trình bày theo kiểu BorderLayout thì:

  • Bộ trình bày khung chứa được chia làm 4 vùng: NORTH, SOUTH, West, eastvà (Đông, Tây, Nam, Bắc và trung tâm). Bộ trình bày lo ại này cho phép sắp xếp và thay đổi kích thước của những components chứa trong nó sao cho vứa với 5 vùng đông, tây, nam, bắc, trung tâm.
  • Không cần phải gắn component vào cho tất cả các vùng.
  • Các component ở vùng NORTH và SOUTH có chiều cao tùy ý nhưng có chiều rộng đúng bằng chiều rộng vùng chứa.
  • Các component ở vùng EAST và WEST có chiều rộng tùy ý nhưng có chiều cao đúng bằng chiều cao vùng chứa.
  • Các component ở vùng CENTER có chiều cao và chiều rộng phụ thuộc vào các vùng xung quanh.

Ví dụ:

import java.awt. *;

class BorderLayoutDemo extends Frame {

private Button north, south, east, west, center; public BorderLayoutDemo(String sTitle)

{

super(sTitle);

north = new Button(“North”);

south = new Button(“South”);

east    = new Button(“East”);

west   = new Button(“West”);

center = new Button(“Center”);

this. add(north, BorderLayout. NOR TH);

this.add(south, BorderLayout.SOUTH);

this.add(east, BorderLayout.EAST);

this.add(west, BorderLayout. WEST);

this.add(center, BorderLayout.CENTER);

}

public static void main(String args[])

{

Frame fr = new BorderLayoutDemo (“BorderLayout

Demo”);

fr.pack();

fr.setVisible(true);

}

}

Kết quả thực thi chương trình:

4.3. GridLayout

public class GridLayout extends Object implements LayoutManager

Đối với một container trình bày theo kiểu GridLayout thì:

  • Bộ trình bày tạo một khung lưới vô hình với các ô bằng nhau.
  • Các đối tượng sẽ đặt vừa kích thước với từng ô đó. Thứ tự sắp xếp từ trái qua phải và từ trên xuống dưới.

Vi du:

import java.awt. *; public class GridLayoutDemo {

public static void main(String arg[])

{

Frame f = new Frame(“GridLayout Demo”); f. setLayout(new GridLayout(3,2));

f.add(new Button(“Red”)); f.add(new Button(“Green”)); f.add(new Button(“Blue “)); f.add(new Checkbox(“Pickme”, true)); f.add(new Label(“Enter name here:”));

f.pack();

f.setVisible(true);

}

Kết quả:

4.4.GridBagLayout

public class GridBagLayout extends Object implements LayoutManager2 (public interface LayoutManager2 extends LayoutManager)

Đối với một container trình bày theo kiểu GridBagLayout thì:

  • Các componets khi được đưa vào khung chứa sẽ được trình bày trên 1 khung lưới vô hình tương tự như GridLayout. Tuy nhiên khác với GridLayout kích thước các đối tượng không nhất thiết phải vừa với 1 ô trên khung lưới mà có thể là 2, 3 ô hay nhiều hơn tùy theo các ràng buộc mà ta chỉ định thông qua đối tượng GridBagConstraints.
  • Lớp GridBagConstraints dẫn xuất từ lớp Object. Lớp GridBagConstraints dùng để chỉ định ràng buộc cho những components trình bày trong khung chứa container theo kiểu
    • gridx, gridy: vị trí ô của khung lưới vô hình mà ta sẽ đưa đối tượng con vào
    • gridwidth, gridheight: kích thước hay vùng trình bày cho đối tượng con. o Insets: là một biến đối tượng thuộc lớp Inset dùng để qui định khoảng cách biên phân cách theo 4 chiều (trên, dưới, trái, phải). o weightx, weighty: chỉ định khoảng cách lớn ra tương đối của các đối tượng con với nhau

Ví dụ:

import java.awt. *; public class GridBagLayoutDemo {

public static void main(String arg[])

{

Frame f = new Frame(“GridBagLayout Demo”);

// Thiet lap layout manager

// Tao doi tuong rang buoc cho cach trinh bay

// GridBagLayout.

GridBagLayout layout = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); f. setLayout(layout);

// Tao ra 9 nut nhan

String[] buttName = {“Mot”, “Hai”, “Ba”, “Bon”,

“Nam”, “Sau”, “Bay”, “Tam”, “Chin”};

Button[] buttons = new Button[9];

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

{

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

}

// Rang buoc cac nut nhan cach nhau 2 pixel

// Qui dinh cac nut nhan se thay doi kick thuoc // theo ca 2 chieu

constraints.fill = GridBagConstraints.BOTH;

// Rang buoc cho nut nhan thu 1 constraints.gridx = 1; constraints.gridy = 1; constraints.gridheight = 2; constraints.gridwidth = 1; layout.setConstraints(buttons[0], constraints);

// Rang buoc cho nut nhan thu 2 constraints.gridx = 2; constraints.gridy = 1; constraints.gridheight = 1; constraints.gridwidth = 2; layout.setConstraints(buttons[1], constraints);

// Rang buoc cho nut nhan thu 3 constraints.gridx = 2; constraints.gridy = 2; constraints.gridheight = 1; constraints.gridwidth = 1; layout.setConstraints(buttons[2], constraints);

// Rang buoc cho nut nhan thu 4 constraints.gridx = 1; constraints.gridy = 3; constraints.gridheight = 1; constraints.gridwidth = 2; layout.setConstraints(buttons[3], constraints);

// Rang buoc cho nut nhan thu 5

constraints.gridx = 3; constraints.gridy = 2; constraints.gridheight = 2; constraints.gridwidth = 1; layout.setConstraints(buttons[4], constraints);

// Rang buoc cho nut nhan thu 6 constraints.gridx = 4; constraints.gridy = 1; constraints.gridheight = 3; constraints.gridwidth = 1; layout.setConstraints(buttons[5], constraints);

// Tu nut thu 7 tro di khong can rang buoc

// thay vi doi kich thuoc

constraints.fill = GridBagConstraints.NONE;

// Rang buoc cho nut nhan thu 7 constraints.gridx = 1; constraints.gridy = 4; constraints.gridheight = 1; constraints.gridwidth = 1; constraintsweightx = 1.0; layout.setConstraints(buttons[6], constraints);

// Rang buoc cho nut nhan thu 8 constraints.gridx = 2; constraints.gridy = 5; constraints.gridheight = 1; constraints.gridwidth = 1; constraintsweightx = 2.0; layout.setConstraints(buttons[7], constraints);

// Rang buoc cho nut nhan thu 9 constraints.gridx = 3;

constraints.gridy = 6; constraints.gridheight = 1; constraints.gridwidth = 1; constraints.weightx = 3.0; layout.setConstraints(buttons[8], constraints);

// Dua cac nut nhan khung chua chuong trinh for (int i=0;i<9;i++) f. add(buttons[i]);

f.pack();

f.setVisible(true);

}

Kết quả:

4.5. Null Layout

Một khung chứa được trình bày theo kiểu Null Layout có nghĩa là người lập trình phải tự làm tất cả từ việc qui định kích thước của khung chứa, cũng như kích thước và vị trí của từng đối tượng component trong khung chứa.

Để thiết lập cách trình bày là Null Layout cho một container ta chỉ việc gọi phương thức setLayout(null) với tham số là null.

Một số phương thức của lớp trừu tượng Component dùng để định vị và qui định kích thước của component khi đưa chúng vào       khung chứa   trình bày theo kiểu kiểu tự do:

  • Public void   setLocation(Point p)
  • Public void   setSize(Dimension p)
  • Public void   setBounds(Rectangle r)

Ví dụ:

 MyButton.setSize(new Dimension(20, 10)); o MyButton.setLocation(new Point(10, 10)); o MyButton.setBounds(10, 10, 20, 10);

import java.awt. *; class NullLayoutDemo {

public static void main(String args[])

{ 2

Frame fr = new Frame(“NullLayout Demo”);

fr. setLayout(null);

Button buttOk = new Button(“OK”);

buttOk.setBounds(100, 150, 50, 30);

Button buttCancel = new Button(“Cancel”);

buttCancel.setBounds(200, 150, 50, 30);

Checkbox checkBut = new Checkbox(“Check

box”, true);

checkBut.setBounds(100, 50, 100, 20);

List li = new List(); for (int i=0; i<5; i++)

{

li.add(Integer. toString(i));

}

li.setBounds(200, 50, 50, 50);

fr.add(buttOk); fr. add(buttCancel);

fr. add(checkBut); fr.add(li);

fr.setBounds(10, 10, 400, 200); fr.setVisible(true);

}

}

Kết quả:

5. Các đối tượng khung chứa Container

Như chúng ta đã biết container là đối tượng khung chứa có khả năng quản lý và chứa các đối tượng (components) khác trong nó.

Các components chỉ có thể sử dụng được khi đưa nó vào 1 đối tượng khung chứa là container.

Mỗi container thường gắn với một LayoutManager (FlowLayout, BorderLayout, GridLayout, GridBagLayout, Null Layout) qui định cách trình bày và bố trí các components trong một container.

Các lọai container trong java: Frame, Panel, Dialog, ScrollPanes.

5.1.Khung chứa Frame

java.lang.Object

+–java.awt.Component

+–ịava.awt.Container

+–ịava.awt.Window

+–j ava.awt.Frame

Khung chứa Frame là một cửa số window hẳn hoi ở mức trên cùng bao gồm một tiêu đều và một đường biên (border) như các ứng dụng windows thông thường khác. Khung chứa Frame thường được sử dụng để tạo ra cửa sổ chính của các ứng dụng.

Khung chứa Panel có bộ quản lý trình bày (LayoutManager) mặc định là FlowLayout.

5.2. Khung chứa Panel

ịava.lang.Obịect

+–ịava.awt.Component

+–ịava.awt.Container

+–java.awt.Panel

Khung chứa Panel có bộ quản lý trình bày (LayoutManager) mặc định là FlowLayout.

Đối với khung chứa Panel thì các Panel có thể lồng vào nhau, vì vậy khung chứa Panel thường được dùng để bố trí các nhóm components bên trong một khung chứa khác.

Ví dụ:

import java.awt. *;

public class PanelDemo extends Frame {

private Button next, prev, first; private List li;

public PanelDemo(String sTitle)

{

super(sTitle);

next = new Button(“Next >>”); prev = new Button(“<< Prev”);

Panel southPanel = new Panel(); southPanel. add(next); southPanel. add(prev); southPanel. addfirst);

//BorderLayout.SOUTH: vùng dưới

this.add(southPanel, BorderLayout.SOUTH);

Panel northPanel = new Panel(); northPanel.add(new Label(“Make a Selection”)); //BorderLayout.NORTH: vùng trên this.add(northPanel, BorderLayout.NORTH);

li = new List(); for(int i=0;i<10;i++)

{

li.add(“Selection” + i);

}

this.add(li, BorderLayout.CENTER);

}

public static void main(String arg[])

{

Container f = new PanelDemo(“PanelDemo”);

f.setSize(300, 200);

f.setVisible(true);

}

}

Kết quả thực thi chương trình:

5.3. Khung chứa Dialog

+–java.awt.Dialog

Dialog là một lớp khung chứa tựa Frame và còn được gọi là popup window. Có hai lo ại dialog phổ biến:

Modal Dialog: sẽ khóa tất cả các cửa số khác của ứng dụng khi dialog dạng này còn hiển thị.

Non-Modal Dialog: vẫn có thể đến các cửa số khác của ứng dụng khi dialog dạng này hiển thị.

Một cửa sổ dạng Dialog luôn luôn phải gắn với một cửa sổ ứng dụng (Frame).

Để tạo một đối tượng khung chứa Dialog ta có thể dùng một trong các constructor của nó:

public Dialog (Frame parentWindow, boolean isModal)

public Dialog (Frame parentWindow, String title,

boolean isModal)

parentWindow: cửa sổ cha

title: tiêu đề của Dialog

isModal: true -> là Dialog dạng modal

isModal: false -> là Dialog không phải dạng modal

(hay non-modal)

6. Xử lý biến cố/sự kiện

6.1.Mô hình xử lý sự kiện (Event-Handling Model)

Ở trên chúng ta   chỉ đề cập đến vấn đề thiết kế giao diện chương trình  ứng dụng mà chưa đề cập đến vấn đề xử  lý  sự kiện. Những sự kiện được phát sinh khi người dùng tương tác với giao diện chương trình (GUI). Những tương tác thường gặp như: di chuyển, nhấn chuột, nhấn một nút nhấn, chọn một MenuItem trong                     hệ           thống       thực  đơn,     nhập dữ   liệu            trong   một      ô văn bản, đóng cửa sổ ứng dụng, … Khi có một tương tác xảy ra thì một sự kiện được gởi đến chương trình. Thông tin về sự kiện thường      được   lưu   trữ     trong      một      đối       tượng  dẫn     xuất     từ  lớp AWTEvent. Những kiểu sự kiện trong gói java.awt.event có thể dùng cho cả những component AWT và JFC. Đối với thư viện JFC thì có thêm những kiểu sự kiện mới trong gói java.swing.event.

Có 3 yếu tố quan trọng trong mô hình xử lý sự kiện:

  • Nguồn phát sinh sự kiện (event source)
  • Sự kiện (event object)
  • Bộ lắng nghe sự kiện (event listener)

Nguồn phát sinh sự kiện: là thành phần của giao diện mà người dùng tác động.

Sự kiện: Tóm tắt thông tin về xử kiện xảy ra, bao gồm tham chiếu đến  nguồn gốc      phát sinh sự kiện  và thông tin sự kiện sẽ gởi đến cho bộ lắng nghe xử lý.

Bộ lắng nghe: Một bộ lắng nghe là một đối tượng của một lớp hiện thực một hay nhiều interface của gói java.awt.event hay java.swing.event (đối với những component trong thư viện JFC). Khi được thông báo, bộ lắng nghe nhận sự kiện và xử lý. Nguồn phát sinh       sự        kiện     phải    cung   cấp                               những  phương    thức           để đăng ký   hoặc hủy bỏ  một bộ  lắng nghe. Nguồn phát sinh sự kiện luôn phải gắn với một bộ lắng nghe, và nó sẽ thông báo với bộ lắng nghe đó khi có sự kiện phát sinh đó.

Như vậy người lập trình cần làm hai việc:

  • Tạo và đăng ký một bộ lắng nghe cho một component trên GUI.
  • Cài đặt các phương thức quản lý và xử lý sự kiện Những interfaces lắng nghe của gói awt. event

ActlonLlstener

Một đối tượng Event-Listener lắng nghe những sự kiện khác nhau phát sinh từ các components của giao diện chương trình. Với mỗi sự kiện khác nhau phát sinh thì phương thức tương ứng trong những Event-Listener sẽ được gọi thực hiện.

Mỗi interface Event-Listener gồm một hay nhiều các phương thức mà chúng cần cài đặt trong các lớp hiện thực (implements) interface đó. Những phương thức trong các interface là trừu tượng vì vậy lớp (bộ lắng nghe) nào hiện thực các interface thì
phải cài đặt tất cả những phương thức đó. Nếu không thì các bộ lắng nghe sẽ trở thành các lớp trừu tượng.

6.2. Xử lý sự kiện chuột

Java cung cấp hai intefaces lắng nghe (bộ lắng nghe sự kiện chuột) là MouseListener và MouseMotionListener để quản lý và xử lý các sự kiện liên quan đến thiết bị chuột. Những sự kiện chuột có thể “bẫy” cho bất kỳ component nào trên GUI mà dẫn xuất từ java.awt.component.

Các phương thức của interface MouseListener:

  • public void mousePressed(MouseEvent event): được gọi khi một nút chuột được nhấnvà con trỏ chuột ở trên component.
  • public void mouseClicked(MouseEvent event): được gọi khi một nút chuột được nhấn và nhả trên component mà không di chuyển chuột.
  • public void mouseReleased(MouseEvent event): được gọi khi một nút chuột nhả sa khi kéo rê.
  • public void mouseEntered(MouseEvent event): được gọi khi con trỏ chuột vào trong đường biên của một component.
  • public void mouseExited(MouseEvent event) :được gọi khi con trỏ chuột ra khỏi đường biên của một component.

Các phương thức của interface MouseMotionListener:

  • public void mouseDragged(MouseEvent even ): phương thức này được gọi khi người dùng nhấn một nút chuột và kéo trên một component.
  • public void mouseMoved(MouseEvent event): phương thức này được gọi khi di chuyển chuột trên component.

Mỗi   phương thức  xử  lý  sự  kiện chuột có  một  tham  số MouseEvent chứa thông tin về sự kiện chuột phát sinh chẳng hạn như: tọa độ x, y nơi sự kiện chuột xảy ra. Những phương thức tương ứng trong các interfaces sẽ tự động được gọi khi chuột tương tác với một component.

Để biết được người dùng đã nhấn nút chuột nào, chúng ta dùng những phuơng thức, những hằng số của lớp InputEvent (là lớp cha của lớp MouseEvent).

6.3. Xử lý sự kiện bàn phím

Để xử lý sự kiện bàn phím java hỗ trợ một bộ lắng nghe sự kiện đó là interface KeyListener. Một sự kiện bàn phím được

phát sinh khi người dùng nhấn và nhả một phím trên bàn phím. Một lớp       hiện    thực     KeyListener                phải cài    đặt                các  phương       thức keyPressed, keyReleased và keyTyped. Mỗi phương thức này có một tham số là một đối tượng kiểu KeyEvent. KeyEvent là lớp con của lớp InputEvent.

Các phương thức của interface KeyListener

  • Phương thức keyPressedđược gọi khi một phím bất kỳ được nhấn.
  • Phương thức keyTypedđược gọi thực hiện khi người dùng nhấn một phím không phải “phím hành động” (như phím mũi tên, phím Home, End, Page Up, Page Down, các phím chức năng như: Num Lock, Print Screen, Scroll Lock, Caps Lock, Pause).
  • Phương thức keyReleasedđược gọi thực hiện khi nhả phím nhấn sau khi sự kiện keyPressedhoặc

Ví dụ: minh họa việc xử lý sự kiện chuột thông qua các phương thức của interface KeyListener. Lớp KeyDemo bên dưới hiện thực interface KeyListener, vì vậy tất cả 3 phương thức trong KeyListener phải được cài đặt trong chương trình.

// KeyDemo.java

// Demonstrating keystroke events.

// Java core packages import java.awt. *; import java.awt.event. *;

public class KeyDemo extends Frame implements KeyListener {

private String linel = line2 = “”; private String line3 = “”; private TextArea textArea;

// set up GUI public KeyDemo()

// set up TextArea

textArea = new TextArea( 10, 15);

textArea.setText( “Press any key on the keyboard… “);

textArea.setEnabled( false );

this.add( textArea );

// allow frame to process Key events addKeyListener( this );

setSize( 350, 100 ); setVisible( true );

}

// handle press of any key

public void keyPressed( KeyEvent event )

{

linel = “Key pressed: ” + event.getKeyText( event.getKeyCode() ); setLines2and3( event);

}

// handle release of any key

public void keyReleased( KeyEvent event)

{

linel = “Key released: ” + event.getKeyText( event.getKeyCode() ); setLines2and3( event);

}

// handle press of an action key public void keyTyped( KeyEvent event )

{

linel = “Key typed: ” + event.getKeyChar(); setLines2and3( event);

// set second and third lines of output private void setLines2and3(KeyEvent event)

{

line2 = “This key is ” + (event.isActionKey() ? “” : “not “) + “an action key”;

String temp = event.getKeyModifiersText( event.getModifiers() );

line3 = “Modifier keys pressed: ” + (temp.equals( “”) ? “none” : temp );

textArea.setText(line1 + “\n”+line2+ “\n”+ line3+ “\n” );

}

// execute application

public static void main( String args[] )

{

KeyDemo application = new KeyDemo();

}

} // end class KeyDemo