Xử lý cỏc sự kiện trong Java

Một phần của tài liệu giáo trình về java 2008 (Trang 93)

I. Khỏi niệm và cơ sở xử lý sự kiện

Bất kỳ chương trỡnh cú giao diện đồ họa nào thường hỗ trợ việc kớch hoạt cỏc sự kiện từ con chuột hoặc bàn phớm. Mụi trường điều hành sẽ gửi cỏc sự kiện này tới chương trỡnh đang chạy. Lập trỡnh viờn được hoàn toàn quyết định điều gỡ sẽ xảy ra khi cỏc sự kiện này được kớch hoạt.

Trong Java sử dụng một cỏch tiếp cận dựa trờn cỏc khỏi niệm: - Cỏc nguồn của sự kiện (event source)

- Cỏc bộ lắng nghe sự kiện (event listener)

Cỏc nguồn sự kiện chớnh là cỏc đối tượng điều khiển, chỳng cú cỏc phương thức để lập trỡnh viờn đăng ký cỏc bộ lắng nghe cho chỳng. Khi một sự kiện xảy ra đối với một nguồn sự kiện, nú sẽ gửi thụng bỏo này tới tất cả cỏc bộ lắng nghe sự kiện được đăng ký cho sự kiện đú.

Đối với một ngụn ngữ OOP như Java thỡ toàn bộ thụng tin về sự kiện được đúng gúi trong một lớp event. Tất cả cỏc lớp event đều dẫn xuất từ lớp java.util.EventObject. Mỗi loại sự kiện tương ứng với một lớp dẫn xuất, chẳng hạn như ActionEvent và WindowEvent. Sau đõy là cõy phõn cấp chỉ sự kế thừa giữa cỏc lớp sự kiện trong Java:

Cỏc sự kiện trờn được gửi cho cỏc đối tượng lắng nghe tương ứng như: ActionListener MouseMotionListener AdjustmentListener MouseWheelListener FocusListener WindowListener ItemListener WindowFocusListener KeyListener WindowStateListener MouseListener

Cỏc nguồn sự kiện khỏc nhau cú thể phỏt sinh cỏc sự kiện khỏc nhau. Vớ dụ một button (nỳt bấm) thỡ phỏt sinh sự kiện ActionEvent trong khi một cửa sổ lại phỏt sinh sự kiện WindowEvent.

Túm lại, một sự kiện được quản lý dựa trờn cỏc khỏi niệm:

1. Một đối tượng lắng nghe là một biểu hiện của một lớp cú cài đặt giao diện lắng nghe sự kiện

2. Một nguồn sự kiện là một đối tượng mà cú thể đăng ký cỏc đối tượng lắng nghe và gửi cho chỳng cỏc đối tượng sự kiện.

3. Nguồn sự kiện gửi đối tượng sự kiện tới tất cả cỏc đối tượng lắng nghe được đăng ký cho sự kiện đú.

4. Đối tượng lắng nghe sẽ sử dụng thụng tin trong cỏc đối tượng sự kiện để phản ứng với cỏc sự kiện đú.

Cỳ phỏp để đăng ký cỏc đối tượng lắng nghe cho cỏc nguồn sự kiện theo cỳ phỏp sau: <nguồn sự kiện>.add<sự kiện>Listener(<đối tượng lắng nghe sự kiện>)

Vớ dụ:

ActionListener listener = . . .; // đối tượng lắng nghe JButton button = new JButton("Ok"); // Nguồn sự kiện

button.addActionListener(listener); // đăng ký đối tượng lắng nghe sự kiện

Trong đoạn code trờn, vấn đề cũn lại là đối tượng lắng nghe sự kiện phải cú một phương thức để nhận về sự kiện từ nguồn sự kiện đăng ký nú và xử lý. Ở đõy, đối tượng listener phải thuộc một lớp cú cài đặt giao diện ActionListener. Trong giao diện này cú khai bỏo một phương thức actionPerformed để nhận về một sự kiện ActionEvent:

class MyListener implements ActionListener {

. . .

public void actionPerformed(ActionEvent event) {

// Đoạn mó xử ký sự kiện đặt ở đõy . . .

} }

Bất cứ khi nào người dựng click chuột vào đối tượng Jbutton trờn màn hỡnh, một sự kiện ActionEvent được phỏt sinh và gửi cho đối tượng lắng nghe listener. Đối tượng này cú cài đặt một phương thức để xử lý sự kiện là actionPerformed, lấy đối số là đối tượng ActionEvent nhận được.

Cú thể cú nhiều bộ lắng nghe được đăng ký cho một nguồn sự kiện, khi đú sự kiện cũng được gửi tới tất cả cỏc bộ lắng nghe và tới phương thức actionPerformed của chỳng.

Sau đõy là một vớ dụ về xử lý sự kiện click cho 3 đối tượng Jbutton:

Một Button được tạo ra như sau bằng cỏch gọi constructor của JButton với một chuỗi nhón hoặc một ảnh hay cả hai:

JButton yellowButton = new JButton("Yellow");

JButton blueButton = new JButton(new ImageIcon("blue-ball.gif")); Thờm 3 Button vào 1 panel như sau:

Class ButtonPanel extends JPanel {

public ButtonPanel() {

JButton yellowButton = new JButton("Yellow"); JButton blueButton = new JButton("Blue");

JButton redButton = new JButton("Red"); add(yellowButton); add(blueButton); add(redButton); } }

Bõy giờ chỳng ta định nghĩacỏc bộ lắng nghe cho cỏc Button này gọi là ColorAction như sau:

public class ColorAction implements ActionListener {

public ColorAction(Color c) {

backgroundColor =c; }

public void actionPerformed(ActionEvent e) {

setBackground(backgroundColor); // Thay đổi màu nền của panel khi Button được click }

private Color backgroundColor; }

Mỗi đối tượng Button được đăng ký cho bộ lắng nghe này: Class ButtonPanel extends JPanel

{

public ButtonPanel() {

JButton yellowButton = new JButton("Yellow"); JButton blueButton = new JButton("Blue"); JButton redButton = new JButton("Red"); add(yellowButton);

add(blueButton); add(redButton);

ColorAction yellowAction = new ColorAction(Color.Yellow); ColorAction blueAction = new ColorAction(Color.Blue); ColorAction redAction = new ColorAction(Color.Red); yellowButton.addActionListener(yellowAction); blueButton.addActionListener(blueAction); redButton.addActionListener(redAction); }

}

Một vấn đề đặt ra là phương thức setBackground() khụng được định nghĩa trong lớp ColorAction mà chỉ được định nghĩa cho lớp Panel. Giải phỏp ở đõy là đưa lớp ColorAction

thành lớp nội của lớp ButtonPanel, khi đú trong lớp ColorAction, ta cú thể truy cập cỏc phương thức của lớp Panel (được ButtonPanel kế thừa) như setBackground chẳng hạn.

Class ButtonPanel extends JPanel {

public ButtonPanel() {

JButton yellowButton = new JButton("Yellow"); JButton blueButton = new JButton("Blue"); JButton redButton = new JButton("Red"); add(yellowButton);

add(blueButton); add(redButton);

ColorAction yellowAction = new ColorAction(Color.Yellow); ColorAction blueAction = new ColorAction(Color.Blue); ColorAction redAction = new ColorAction(Color.Red);

yellowButton.addActionListener(yellowAction); // Đăng ký bộ lắng nghe sự kiện blueButton.addActionListener(blueAction);

redButton.addActionListener(redAction); }

private class ColorAction implements ActionListener {

public ColorAction(Color c) {

backgroundColor =c; }

public void actionPerformed(ActionEvent e) {

setBackground(backgroundColor); // Thay đổi màu nền của panel khi Button được click }

private Color backgroundColor; }

}

Chương trỡnh sau đõy kiểm tra sự thực hiện đỏp ứng cỏc sự kiện vừa thiết kế ở trờn: import javax.swing.JFrame;

public class testPanel extends JFrame {

public testPanel() {

ButtonPanel pn = new ButtonPanel(); this.add(pn);

}

{

testPanel p = new testPanel(); p.setSize(300,400);

p.setVisible(true); }

}

Thụng thường, cỏc lớp lắng nghe sự kiện cú thể được cài đặt ngay trong phương thức addActionListener như sau:

yellowButton.addActionListener( new ActionListener()

{

public void actionPerformed(ActionEvent event) {

setBackground(Color.YELLOW); }

});

Làm như vậy ta khụng cần thiết kế riờng một lớp ColorAction.

II. Truy cập thụng tin sự kiện

Một phương phỏp khỏc để lập trỡnh sự kiện đú là gỏn cho tất cả cỏc đối tượng nguồn sự kiện chung một đối tượng lắng nghe. Tựy theo thụng tin về sự kiện nhận được, phương thức actionPerformed sẽ cú sự hành xử khỏc nhau. Muốn vậy, lớp chứa cỏc nguồn sự kiện phải cài đặt giao diện ActionListener.

import javax.swing.*; import java.awt.event.*;

public class ButtonPanel extends JPanel implements ActionListener { JButton yellowButton;

JButton blueButton; JButton redButton; public ButtonPanel() {

yellowButton = new JButton("Yellow"); blueButton = new JButton("Blue"); redButton = new JButton("Red"); add(yellowButton); add(blueButton); add(redButton); yellowButton.addActionListener(this); blueButton.addActionListener(this); redButton.addActionListener(this); }

public void actionPerformed(ActionEvent event) {

if (event.getSource()==yellowButton) setBackground(Color.YELLOW); if (event.getSource()==redButton) setBackground(Color.RED);

if (event.getSource()==blueButton) setBackground(Color.BLUE); }

}

Trong vớ dụ trờn, bản thõn lớp component ButtonPanel đúng vai trũ là lớp lắng nghe sự kiện vỡ nú cú cài đặt giao diện ActionListener. Do đú, khi đăng ký đối tượng lắng nghe cho cỏc Button, ta chỉ việc sử dụng biến this, đại diện cho đối tượng ngầm định của chớnh lớp ButtonPanel. Cỏc đối tượng Button bõy giờ cũng phải khai bỏo là biến thành phần của lớp vỡ chỳng được truy cập trong 2 phương thức khỏc nhau. Tuy nhiờn phương phỏp này sẽ trở nờn khú dựng khi trờn panel cú nhiều đối tượng nguồn sự kiện.

III. Xử lý cỏc sự kiện trờn window

Phần trờn đó cho thấy cỏch thức chỳng ta làm việc với cỏc nguồn sự kiện là cỏc đối tượng nằm trong một window. Phần này ta sẽ xem xột cỏc sự kiện xảy ra đối với bản thõn một window.

Muốn bắt cỏc sự kiện của window, ta cũng qua cỏc bước căn bản sau: WindowListener listener = new .....

frame.addWindowListener(listener);

Trong đú frame là một đối tượng của lớp JFrame, là đối tượng nguồn sự kiện phỏt sinh cỏc sự kiện WindowEvent. Đối tượng listener bắt buộc phải thuộc một lớp cú cài đặt giao diện WindowListener. Cấu trỳc của giao diện này như sau:

public interface WindowListener {

void windowOpened(WindowEvent e); void windowClosing(WindowEvent e); void windowClosed(WindowEvent e);

void windowIconified(WindowEvent e); // thu nhỏ của sổ void windowDeiconified(WindowEvent e);

void windowActivated(WindowEvent e); void windowDeactivated(WindowEvent e); }

Do đú cỏc lớp cài đặt giao diện này phải khai bỏo định nghĩa tất cả cỏc phương thức trờn. Tuy nhiờn, ta chỉ viết code cho phương thức nào ta xử lý mà thụi, vớ dụ:

class Terminator implements WindowListener {

public void windowClosing(WindowEvent e) {

System.exit(0); }

public void windowOpened(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowActivated(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} }

IV. Cỏc lớp thớch nghi

Ta thấy rằng việc khai bỏo đầy đủ 7 phương thức, cú những phương thức khụng xử lý gỡ cả làm cho chương trỡnh khụng được tối ưu. Giải phỏp ở đõy sẽ là định nghĩa một lớp trung gian, khai bỏo cài đặt giao diện WindowListener với đầy đủ 7 phương thức nhưng cỏc phương thức này cũng khụng làm gỡ cả. Cỏc lớp muốn cài đặt nội dung cho một sự kiện chỉ việc khai bỏo kế thừa lớp này và định nghĩa chồng phương thức cần thiết. Cỏc lớp cú vai trũ trung gian như vậy gọi là cỏc lớp thớch nghi. Với mỗi giao diện lắng nghe, ta cú một lớp thớch nghi tương ứng. Vớ dụ: WindowListener cú lớp thớch nghi WindowAdapter, MouseListener cú MouseAdapter. Cỏc lớp thớch nghi thường dựng là:

FocusAdapter MouseMotionAdapter KeyAdapter WindowAdapter MouseAdapter

class Terminator extends WindowAdapter {

public void windowClosing(WindowEvent e) {

System.exit(0); }

}

Vấn đề là cỏc lớp window thường phải khai bỏo kế thừa từ JFrame rồi nờn khụng thể khai bỏo kế thừa thờm lớp WindowAdapter. Lỳc này, kỹ thuật định nghĩa lớp nội nặc danh được phỏt huy:

frame.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent event) {

System.exit(0); }

public void windowIconified(WindowEvent e) {System.exit(0);} } );

Đoạn code này thực hiện cỏc cụng việc sau:

1. Định nghĩa một class nặc danh kế thừa lớp WindowAdapter

2. Thờm 2 phương thức windowClosing và windowIconified cho lớp nặc danh đú 3. Kế thừa 5 phương thức cũn lại từ WindowAdapter

4. Tạo ra một đối tượng của lớp đú, đối tượng cũng khụng cú tờn 5. Gửi đối tượng này cho phương thức addWindowListener

Ta cú thể định nghĩa chồng nhiều hơn một phương thức của WindowAdapter.

Tất nhiờn là khụng phải khi nào ta cũng phải sử dụng lớp nội nặc danh. Một cỏch làm khỏc là khai bỏo một lớp (thường là lớp nội) dạng như class Terminator ở trờn, sau đú đăng ký lắng nghe sự kiện cho frame mà khụng cần một đối tượng cú tờn rừ ràng của Terminator:

frame.addWindowListener(new Terminator());

Để kết thỳc đề tài này ta liệt kờ cỏc phương thức xử lý sự kiện như bảng sau:

Interface Methods Parameter/Accessors Nguồn sự kiện

ActionListener actionPerformed ActionEvent

 getActionCommand  getModifiers AbstractButton JComboBox JTextField Timer AdjustmentListener adjustmentvalueChanged AdjustmentEvent

 getAdjustable

 getAdjustmentType

 getValue

JScrollbar

ItemListener ItemstateChanged ItemEvent

 getItem  getItemSelectable  getStateChange AbstractButton JComboBox FocusListener FocusGained focusLost FocusEvent  isTemporary Component KeyListener keyPressed keyReleased keyTyped KeyEvent  getKeyChar  getKeyCode  getKeyModifiersText  getKeyText  isActionKey Component MouseListener mousePressed mouseReleased mouseEntered mouseExited mouseClicked MouseEvent  getClickCount  getX  getY  getPoint  TRanslatePoint Component MouseMotionListener mouseDragged mouseMoved MouseEvent Component

Interface Methods Parameter/Accessors Nguồn sự kiện

MouseWheelListener mousewheelMoved MouseWheelEvent

 getWheelRotation  getScrollAmount Component WindowListener windowClosing windowOpened windowIconified windowDeiconified windowClosed windowActivated windowDeactivated WindowEvent  getWindow Window WindowFocusListener windowGainedfocus windowlostFocus WindowEvent  getOppositeWindow Window

WindowStateListener WindowStateChanged WindowEvent

 getOldState

 getNewState

Window

V. Xử lý cỏc sự kiện chuột

Cỏc sự kiện với chuột được xử lý bởi giao diện MouseListener. Khi một nguồn sự kiện được kớch hoạt bởi việc click chuột, cỏc phương thức xử lý cho cỏc sự kiện tương ứng được liệt kờ trong bảng trờn, đặc biệt hay dựng là mouseClicked(). Thụng thương ta cũng khụng cài đặt xử lý cho tất cả cỏc sự kiện này nờn ta khụng cài đặt giao diện MouseListener mà khai bỏo một lớp nội nặc danh kế thừa từ lớp thớch nghi MouseAdapter.

Giả sử cú một đối tượng JFrame tờn là frame, sau đõy là một vớ dụ quản lý sự kiện click chuột trờn nú:

frame. addMouseListener( new MouseAdapter() {

public void mouseClicked(MouseEvent e) // Mac dinh la chuot trai { // Kiem tra neu la chuot phai duoc click

if( (e.getModifiers() & InputEvent.BUTTON3_MASK)== InputEvent.BUTTON3_MASK) // hien thi mot popup menu tai vi tri click

jp.show(getContentPane(),e.getX(),e.getY()); }

} );

Tham khảo thờm tại:

và http://java.sun.com/docs/books/tutorial/uiswing/events/mouselistener.html

Bài tập

1. Viết chương trỡnh xử lý sự kiện chuột click trờn cỏc Botton, nếu là chuột trỏi thỡ thụng bỏo là “Bạn vừa click chuột trai”, nếu là chuột phải thỡ thụng bỏo “Bạn vừa click chuột phải”. 2. Viết chương trỡnh sau khi chọn một Button trờn màn hỡnh, nhấn phớm x thỡ chương trỡnh kết thỳc.

Đề tài 9. Applet

Applet là một trong những kỹ thuật vượt trội của Java so với cỏc ngụn ngữ khỏc. Một Applet là một chương trỡnh Java được nhỳng vào trong cỏc trang web, nú đứng một vị trớ độc lập bờn cạnh cỏc phần khỏc của trang web.

I. Xõy dựng một Applet đơn giản

1. Soạn thảo một tệp cú tờn “Hello.java” như sau: import java.applet.Applet; //khai bỏo thư viện import java.awt.Graphics;

//Khai bỏo đồ hoạ

public class Hello extends Applet { //cài đặt phương thức cho Applet public void paint(Graphics g){ g.drawString("Hello!", 50, 25); }

2. Biờn dịch tệp Hello.java

3. Soạn thảo một trang HTML cú tờn hello.htm <html><body>

<applet>

<applet code="Hello.class" width=150 height=25> </applet>

</body></html>

4. Đặt file Hello.class và hello.htm vào trong cựng một thư mục 5. Mở file hello.htm.

Tuy nhiờn để cỏc applet cú thể chạy được, nú cần một JVM trờn mỏy cục bộ. Để cú được JVM cho cỏc trỡnh duyệt ta cần cài phiờn bản Java lờn mỏy tớnh cục bộ và tớch hợp vào trỡnh duyệt như một plug-in.

Trong cỏc phiờn bản Java gần đõy, người lập trỡnh cú thể sử dụng thư viện swing nằm trong gúi javax.swing để cú được giao diện GUI thống nhất trờn mọi hệ thống. Cỏc lớp trong swing cú tờn gọi khỏc so với cỏc lớp trong awt bởi thờm ký tự đầu tiờn “J”.

II. Cấu trỳc cơ bản và vũng đời của một Applet

Một chương trỡnh Applet đầy đủ sẽ bao gồm cỏc thành phần như sau: import java.applet.Applet;

public class myApplet extends Applet{ public void init(){ ...... }

public void start(){ ...... } public void stop() { ...... } public void destroy() { ...... } .... //Cỏc phương thức khỏc }

Nếu dựng JApplet thỡ ta cú khai bỏo phần đầu như sau: import javax.swing.JApplet;

Vũng đời của một Applet được đỏnh dấu bởi cỏc sự kiện diễn ra ở mỗi giai đoạn, lập trỡnh viờn cần nắm được ý nghĩa của từng giai đoạn để cú thể viết code điều khiển Applet:

1. Giai đoạn init: Thực hiện cỏc cụng việc khởi tạo một Applet. Giai đoạn này được bắt đầu ngay sau khi thẻ <param> nằm trong thẻ <applet> được xử lý. Cỏc hành động như thờm cỏc thành phần giao diện người dựng GUI được thực hiện ở đõy. 2. Giai đoạn start: Được thực hiện ngay sau khi giai đoạn init được thực hiện xong.

Nú cũng được gọi bất cứ khi nào người dựng chuyển sang một trang web khỏc rồi quay lại trang cú applet. Do đú, code nằm trong start cú thể được thực hiện nhiều lần trong khi code trong init chỉ được thực hiện 1 lần.

3. Giai đoạn stop: Được thực hiện khi người dựng rời khỏi trang web chứa applet. Do đú, code nằm trong stop cũng cú thể được thực hiện nhiều lần.

4. Giai đoạn destroy: Được thực hiện khi người sử dụng tắt trỡnh duyệt.

Khi viết một applet, chỳng ta khụng phải khi nào cũng cài đặt đầy đủ 4 phương thức mà tựy theo nhu cầu.

Vớ dụ sau xõy dựng một applet cho phộp vẽ liờn tiếp bắt đầu từ vị trớ giữa applet. import java.applet.*;

import java.awt.*; import java.awt.event.*;

public class AppletSample extends Applet {

Point curentPoint; // Lưu tọa độ điểm hiện tại public void init()

{

curentPoint = new Point(this.getWidth()/2,this.getHeight()/2); this.setBackground(Color.CYAN); // đặt màu nền của applet }

public void start() {

this.addMouseListener( new MouseAdapter() {

public void mouseClicked(MouseEvent e)

{ drawOnApplet(curentPoint,e.getPoint()); curentPoint = e.getPoint(); } } ); }

public void drawOnApplet(Point p1, Point p2) {

Graphics g = this.getGraphics(); g.drawLine(p1.x,p1.y,p2.x,p2.y); }

III. An ninh và khả năng của Applet

Vỡ applet được download từ xa và thực hiện trờn mỏy tớnh cụ bộ nờn vấn đề về an ninh được quan tõm đặc biệt. Cỏc nguyờn tắc về an ninh của một applet là:

Một phần của tài liệu giáo trình về java 2008 (Trang 93)

Tải bản đầy đủ (PDF)

(146 trang)