Kinh nghiệm áp dụng Object Oriented trong lập trình Java
lượt xem 27
download
Tác giả muốn phổ biến kinh nghiệm bản thân trong việc áp dụng Object Oriented (OO) với lập trình sử dụng Java. Vấn đề được đặt ra là:“làm thế nào dựa trên phân tích những yêu cầu của một ứng dụng, để tạo ra các lớp (class) hay object cần thiết ?” Hai danh từ class và object sẽ được dùng để chỉ chung một khái niệm trong bài viết này. “Sử dụng những nguyên tắc của OO trong việc phân tích, sẽ giúp cho bạn tìm ra những class hoặc object cần thiết một cách có hệ thống. Giúp...
Bình luận(0) Đăng nhập để gửi bình luận!
Nội dung Text: Kinh nghiệm áp dụng Object Oriented trong lập trình Java
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Kinh nghiệm áp dụng Object Oriented trong lập trình Java Tác giả muốn phổ biến kinh nghiệm bản thân trong việc áp dụng Object Oriented (OO) với lập trình sử dụng Java. Vấn đề được đặt ra là: “làm thế nào dựa trên phân tích những yêu cầu của một ứng dụng, để tạo ra các lớp (class) hay object cần thiết ?” Hai danh từ class và object sẽ được dùng để chỉ chung một khái niệm trong bài viết này. “Sử dụng những nguyên tắc của OO trong việc phân tích, sẽ giúp cho bạn tìm ra những class hoặc object cần thiết một cách có hệ thống. Giúp bạn làm quen và hiểu OO là mục đích chính của bài viết này.” “ Đầu tiên nên tìm hiểu OO được hình thành trong hoàn cảnh nào của việc lập trình“ Trở về thời gian trước khi OO được hình thành, những ngôn ngữ như C, Pascal... dựa trên function hoặc procedure. Toàn bộ ứng dụng là một chuỗi các function và procedure, cái này gọi cái kia cho đến khi program chấm dứt. Ví dụ : Yêu cầu của một ứng dụng là tìm kiếm dữ kiện của thí sinh đưa vào số báo danh, thì cách phân tích có thể sẽ là: 1. Tạo ra một function để nhập số báo danh. 2. Tạo ra một function để truy tìm dữ kiện dựa trên dữ kiện nhập. 3. Tao ra một function để display kết quả tìm được. Cách suy nghĩ hay phân tích như vậy gọi là procedural, gồm nhiều sự kiện xảy ra nối tiếp nhau. Cái ưu điểm của cách phân tích này là intuitive (trực quan). Nó dễ hiểu và gần gũi với suy luận tự nhiên của con người. Chỉ cần khéo léo chia vấn đề thành những operation nhỏ hơn để giải quyết. Mọi chuyện có vẻ như có thể giải quyết khá dễ dàng với cách phân tích này. Lấy một ví dụ khác phức tạp hơn. “Bạn được yêu cầu viết ứng dụng simulate hoat động của một chiếc xe đạp. Làm thế nào để chia nhỏ thành các function hay procedure đây ?” Tất nhiên là được nhưng sẽ khó hơn. Vấn đề sẽ trở nên khó hơn nếu nói đến các hệ thống phức tạp như xe gắn máy, máy bay…..v.v Nếu bạn nhìn hoạt động của chiếc xe đạp theo khía cạnh cơ khí máy móc thì nó hòan toàn đơn giản và dễ hiểu. Nó gồm có pedal gắn liền với đĩa, rồi dây xích, rồi líp, rồi bánh xe. Nó như một cỗ máy cơ khí được tạo thành bởi nhiều bộ phận cơ khí nhỏ và đơn giản. Nếu bạn có hể lập trình giống như vậy, bằng cách lắp ráp nhiều bộ phận nhỏ đơn giản lại với nhau, bài toán sẽ trở nên đơn giản hơn, và OO bắt đầu từ suy nghĩ như vậy. Đọc tới đây bạn sẽ đặt câu hỏi: “chẳng phải phương pháp procedural ở trên cùng là chia bài toán thành những function nhỏ hơn hay sao ? Như vậy OO có gì khác biệt hơn ?” Tất nhiên là có. Function hay procedure là một khái niệm trừu tượng dùng để mô tả hoạt động của một vật cụ thể trong thực tế, trong khi OO cho phép tạo ra những object dựa trên hay bắt chước theo những vật cụ thể. Do đó những object trong OO được “cụ thể hoá hơn” và “dễ hiểu hơn”. Bạn có vẻ chưa tin vào khái niệm OO ! Không sao hết, hãy nhìn vào hoạt động của chiếc xe đạp kỹ lưỡng hơn. Đĩa quay kéo dây xích, dây xích lại kéo lip. Khái niệm OO sẽ đưa đến 3 object như sau: đĩa, dây xích, lip. Nhưng làm thế nào bắt chước được hoạt động của chúng ? Sự tiếp xúc hoặc truyền động trong thực tế, được mô phỏng trong phần mềm bằng cách: object này gọi các method của object khác. Nhìn vào ví dụ dưới đây class DayXich { // method mô tả sự kéo của dây xích public void keo(){ } } class Dia { // method mô tả sự quay của đĩa public void xoay(DayXich dx) { // đĩa truyền động cho dây xích bằng cách // gọi method keo() dx.keo(); } }
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Method xoay() của Đĩa gọi method keo() của DayXich. Bản thân method xoay() sẽ bị gọi bởi method nào đó, và cứ như vậy tạo thành hoạt động của cả cổ máy. Trong OO, khi object A gọi method của object B, thì được gọi một cách văn vẻ là “A send a message to B”, trong thực tế nó chỉ đơn giản là mô phỏng cách thức các bộ phận tiếp xúc hay truyền động để làm việc với nhau. Như vậy khái niệm OO đưa phần mềm phản ánh gần gủi và trung thực hơn hoạt động trong thực tế. Người lập trình cũng giống như một kỹ sư cơ khí, thiết kế, chế tạo và lắp ráp từng bộ phận cho một cỗ máy lớn. Cách suy nghĩ theo OO đòi hỏi người lập trình phải nhìn cả ứng dụng giống như một cỗ máy đang vận hành, tìm hiểu sự hoạt động của từng bộ phận, và làm cho chúng cùng làm việc với nhau. Điều này rất quan trọng cần phải nhấn mạnh một lần nữa: Trước khi có thể tìm ra các class hay object cần thiết cho một ứng dụng, bạn hãy cố gắng hình dung toàn bộ ứng dụng hoạt động giống như một hệ thống gồm nhiều chi tiết, bộ phận nhỏ hoạt động ăn khớp với nhau. Đến đây bạn đã biết được tại sao OO ra đời. Cũng giống như Newton đã phát hiện ra sức hút của trái đất, OO ra đời do sự quan sát và mô phỏng theo sự làm việc của những hệ thống có sẵn. Mục đích chính của chúng ta vẫn là làm sao tìm ra được những object cần thiết cho một ứng dụng. Trong thế giới phần mềm một object trong bất kỳ ứng dụng nào đều có thể là một trong 3 loại: Control, Boundary, Entity. Nếu bạn chưa hiểu rõ ý nghĩa chúng là gì ? Cũng không sao. Thông thường không phải lúc nào cũng dễ dàng xác định loại của một object. Xác định object thuộc loại nào, không phải là yếu tố quan trọng trong việc tìm kiếm object cần thiết cho một ứng dụng. Thu hẹp hơn cho những ứng dụng về web hay Swing người ta đưa ra khái niệm MVC = Model-View-Controller. Như vậy ta có thể so sánh như sau: Control = Controller Boundary = View Entity = Model Thông thường một ứng dụng luôn làm những công việc như sau: 1. Nhập và xuất dữ kiện (input/output). 2. Thay đổi hay kết hợp dữ kiện (manipulate data). 3. Lưu trữ hay truy cập dữ kiện (save or retrieve data from database). Công việc thứ nhất thường đưa đến những object thuộc loại View, công việc 2 và 3 thường đưa đến object thuộc loại Model. Bạn có thể nôn nóng đặt câu hỏi:Như vậy Controller cần khi nào ? Câu trả lời sẽ là mọi ứng dụng đều phải có Controller object. Không có chúng thì ứng dụng sẽ nằm i` ra đó mà không chạy. Điều này được làm rõ khi bạn đọc tiếp theo dưới đây. View hay Boundary object trong ứng dụng tìm kiếm dữ kiện của thí sinh là những object mà người sử dụng có thể nhìn thấy. Có thể là JTextField để nhập dữ kiện, có thể là JTable để hiện kết quả truy tìm. Giả sử có 2 ứng dụng A và B chạy độc lập trong đó ứng dụng A cần dữ kiện được tạo ra từ B, thì View object của A là những object dùng để liên hệ với B để nhận dữ kiện, còn View object của B là những object xuất dữ kiện cho A hoặc cho bất kỳ ứng dụng nào khác. Model hay Entity object thường là những object chứa dữ kiện. Object loại này cũng chứa logic hay những thuật toán thay đổi hay kết hợp dữ kiện mà nó chứa, và cả việc đưa vào hay lấy ra từ database. Nói một cách đại khái, đây là những object 'knows how to do'. Trong ứng dụng truy tìm thí sinh, thì nó chính là TableModel dùng để chứa data cho JTable. Control hay Controller object là những object 'knows what to do next'. Bạn cũng biết là trong Java mọi method đều phải nằm trong một class. Class chứa method main() là một ví dụ của Control hay Controller. Chúng cũng thường là những class có những method chứa logic như sau: if(){ //call some method }else { //call some other method }
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Không có những method này thì ứng dụng không chạy được. Bản thân những method này (hay class chứa nó) chứa đựng algorithm hay logic của ứng dụng. Đến đây bạn đã quen thuộc hơn với khái niệm của những object trong phần mềm của một ứng dụng. Bạn có thể liên hệ được sự hiện diện của chúng với những vật cụ thể ở ngoài thực tế. Bạn cũng có thể phân loại và biết được mục đích tại sao cần có object này hay object khác cho một ứng dụng. Chúng ta sẵn sàng cho bước kế tiếp: “tìm kiếm những object cần thiết cho một ứng dụng” Trở lại ví dụ mô hình xe đạp, thì những class như: Dia, DayXich, Lip thuộc loại nào? Bạn biết chắc rằng cần phải có những class này để mô phỏng theo những bộ phận thực của xe đạp, nhưng khó biết chắc nó thuộc loại nào. Phần mềm ngày càng phức tạp và sự phân loại object cũng ngày càng khó hơn. Tuy nhiên, việc xác định loại của một class hay object không phải là “kim chỉ nam” trong việc tìm kiếm đầy đủ những object cho một ứng dụng. Chúng ta không nên đi tìm kiếm object dựa trên mục đích như: Phải bắt đầu bằng tìm kiếm tất cả những object thuộc loại View, Model, hay Controller cho ứng dụng này Sau khi nắm vững yêu cầu của một ứng dụng, nếu bạn có thể liên hệ được hoạt động của ứng dụng với một cỗ máy hay một hệ thống gồm nhiều bộ phận rời rạc hoạt động với nhau, cũng giống như mô hình hoạt động của xe đạp ở trên, thì đó chính là nơi mà bạn có thể chỉ ra được những object cần thiết. Sự cần thiết cần có của một object không phải dựa trên câu hỏi:“nó thuộc loại object nào ? mà phải dựa trên “nó làm được gì ?”. Có nghĩa là trong mô hình xe đạp cần phải có class DayXich để mô phỏng dây xích của xe đạp. Xác định bản thân class DayXich thuộc loại nào không quan trọng lắm, nhưng nó cần thiết để truyền tương tác giữa Dia và Lip. Việc hình dung ra hoạt động của toàn bộ ứng dụng như một cỗ máy không phải lúc nào cũng dễ dàng. Và trong thực tế không phải phần mềm nào cũng dựa theo một hệ thống cụ thể có sẵn. Trong trường hợp này, nguyên tắc “chia để trị” có thể áp dụng. “Chia để trị” là chia toàn bộ hoạt động của ứng dụng thành nhiều chức năng nhỏ hơn. Mọi chức năng hoạt động theo nguyên tắc hộp đen (a blackbox), và chúng hoạt động càng độc lập với nhau càng tốt. Mọi blackbox nhận dữ kiện và xuất dữ kiện tùy theo chức năng của chúng. Dữ kiện xuất của blackbox này sẽ là dữ kiện nhập của blackbox khác. Mỗi một blackbox sẽ có chức năng đơn giản hơn nhiều so với toàn bộ ứng dụng, và nhờ đó bạn sẽ dễ dàng tìm ra những object cần thiết cho hoạt đông của blackbox hơn. Bạn có biết đây cũng chính là nguyên tắc trong việc chế tạo các thiết bị điện tử. Lấy ví dụ trong computer, bạn có thể tháo rời từng bộ phận như CD drive, hard drive... và mỗi bộ phận luôn có điểm tiếp xúc hoặc dây nối để nối với các bộ phận khác. Cần nhớ rằng mọi blackbox trong một ứng dụng phần mềm chứa một hay nhiều object, và blackbox chỉ là những ranh giới trừu tượng dùng để chia nhỏ vấn đề. Trở lại ví dụ tìm kiếm thí sinh dựa vào số báo danh. Chúng ta có thể chia vấn đề thành 2 blackbox: blackbox 1 (BB1) dùng để nhận dữ kiện và trình bày kết quả; blackbox 2 (BB2) dùng để truy tìm dữ kiện. BB1 có thể chứa JTextField để nhập dữ kiện và JTable để trình bày kết quả. BB2 chứa JButton “Truy Tìm”, và SearchAction liên hệ với JButton thực hiện việc truy tìm. Điểm tiếp xúc hay dây nối giữa các blackbox được thể hiện trong phần mềm bằng method của class hay object. * Đối với BB1 , method getText() của JTextField được dùng như điểm để xuất dữ kiện (là số báo danh của thí sinh trong trường hợp này); và chúng ta cần thêm một điểm để nhận kết quả tìm được. Phân tích đến đây, chúng ta có thể tạo thêm một class ResultTableModel với method addResult() cho BB1 để làm điểm nhận kết quả. ResultTableModel được tạo ra như là một TableModel cho JTable. Chúng ta đã tìm được 3 class cho BB1 gồm có: JTextField, JTable, và ResultTableModel. * Đối với BB2 gồm có 2 class: JButton và SearchAction. BB2 nối với BB1 bằng cách gọi 2 method JTextField.getText() và ResultTableModel.addResult() thông qua Action.actionPerformed() như sau: SearchAction(JTextField jtf,ResultTableModel tm) extends...{ .... public void actionPerformd(ActionEvent a) { String sbd = jtf.getText(); //nhận số báo danh, truy tìm từ database. tm.addResult(ketquatimđược); //kết quả tìm được. } }
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Đến đây bạn nên thấy rằng cách suy nghĩ và phân tích vấn đề sử dụng OO cũng quen thuộc và gần gủi với suy nghĩ và thế giới xung quanh của con người. Sản phẩm của OO là những object với những method phản ánh sự làm việc và tương tác với các object khác. Nó dễ hiểu và dễ truyền đạt hơn là những function và procedure của cách suy nghĩ procedural. Đi xa hơn nữa, những tính chất chỉ có trong OO như inheritance, encapsulation, polymorphism làm cho những ứng dụng trở nên linh hoạt và dễ bảo trì hơn. Trình bày chi tiết của 3 tính chất trên sẽ nằm trong một bài viết khác. Sau đây là những điểm cần lưu ý cho những người mới lập trình theo phương pháp OO nhất là những người đã quen thuộc với cách suy nghĩ procedural: 1. Sai lầm khi cho rằng vì Java là một OO ngôn ngữ, cho nên chỉ cần sử dụng Java thành thạo là bạn sẽ tự nhiên sẽ biết OO. Không hiểu được tại sao OO và những tính chất của nó được hình thành sẽ không biết cách áp dụng đúng đắn. 2. Mỗi một class tìm được trong khi phân tích được xem chính nó là một blackbox nhỏ nhất. Khi viết mã nguồn cho một class bạn nên tự đặt chính bản thân vào địa vị của class đó. Nghĩa là bạn chỉ quan tâm tới việc làm sao biến đổi dữ kiện nhập thành dữ kiện xuất trong phạm vi của class. Không quan tâm đến việc dữ kiện nhập từ đâu tới và ai sẽ là người sử dụng dữ kiện xuất. Nó cũng giống như những bộ phận của xe đạp được tạo ra bởi nhiều người khác nhau, và vẫn có thể lắp ráp được với nhau dễ dàng. Đây là đặc điểm rất quan trọng để phân biệt một người lập trình theo phương pháp OO với một người theo phương pháp procedural. 3. Đến đây nếu bạn nắm vững được thêm 3 tính chất của OO: inheritance, encapsulation, polymorphism thì bạn có thể tự tin vào kỹ năng OO của mình rồi đó. 2. Action Một ngày đẹp trời nọ, sếp của bạn tự nhiên giao cho bạn viết một chương trình thay thế cho cái Notepad của Windows. Lý do đơn giản là ổng ko thích dùng cái của Windows và thứ hai là ổng muốn thử thách trình độ của bạn. Việc đầu tiên bạn nghĩ tới khi tạo GUI cho chương trình là hệ thống menu, và muốn chơi trội hơn Windows bạn quyết định thêm vào một cái toolbar. Bạn bắt tay vào tạo một menu bar. J MenuBar menuBar = new JMenuBar(); JMenu file = new JMenu(“File”); JMenuItem item = new JMenuItem(“New”); item.addActionListener(aMenuListener); file.add(item); item = new JMenuItem(“Open”); item.addActionListener(aMenuListener); file.add(item); item = new JMenuItem(“Save”); item.addActionListener(aMenuListener); file.add(item); item = new JMenuItem(“Exit”); item.addActionListener(aMenuListener); file.addSeparator(); file.add(item); //..... Bạn thêm vào menu bar vài cái menu nữa Edit, Format, View, Help... và cuối cùng bạn gọi phương thức setJMenuBar(menuBar). Vậy là bạn đã có hệ thống menu cho mình. Bước tiếp theo là tạo toolbar: JToolBar toolBar = new JToolBar(); JButton b = new JButton(“New”); b.addActionListener(aButtonListener); toolbar.add(b);
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. b = new JButton(“Open”); b.addActionListener(aButtonListener); toolbar.add(b); //...... getContentPane().add(toolbar, BorderLayout.NORTH); Sau khi có hệ thống menu hoàn chỉnh và một thanh toolbar vừa ý, bạn chợt phát hiện ra rằng chẳng có gì khác nhau giữa action New trên menu file và button New trên toolbar, nhưng bạn lại tạo ra hai lớp khác nhau để lắng nghe sự kiện New. Bạn quyết định chỉ tạo một lớp implements ActionListener interface cho cả menu item và button trên toolbar, hãy xem bạn làm gì trong phương thức actionPerformed(): public void actionPerformed(ActionEvent e) { Object obj = e.getSource(); if(obj instanceof JMenuItem) { JMenuItem item = (JMenuItem)obj; String name = item.getText(); if(“New”.equals(name)) { //................................... } //........................ } else if(obj instanceof JButton) { JButton b = (JButton)obj; String bName = b.getText(); if(“New”.equals(bName)) { //................................ } //................................... } } Từ hệ thống menu bạn cảm thấy choáng vì khối lượng các câu lệnh if...else... Liệu có giải pháp nào tốt hơn không? Tôi nói với bạn là tại sao bạn không sử dụng interface Action có sẵn trong Java nhỉ? Action Interface Action interface kế thừa từ ActionListener interface, điều này có nghĩa là khi bạn implements interface này bạn phải định nghĩa phương thức actionPerformed() và một số phương thức khác. Phương thức add() của JToolBar, JMenu, JPopupMenu nhận vào một tham số là đối tượng implements Action interface, khi action được add vào các container này thì container tự động tạo một component tương ứng, ví dụ: khi bạn add một action và JMenu thì một JMenuItem sẽ được tạo ra, add vào JToolBar thì một JButton sẽ được tạo ra. Và lúc này action sẽ trở thành một ActionListener cho component đó. Khi bạn click chọn menu item, hay click chọn button thì phương thức actionPerformed() sẽ được gọi. Trong Action định nghĩa sẵn một số hằng số: - NAME : tên của Action - SHORT_DESCRIPTION, LONG_DESCRIPTION: tooltip - SMALL_ICON: icon - MNEMONIC_KEY: phím đại diện - ACCELERATOR_KEY: phím tăng tốc - ACTION_COMMAND_KEY: chuỗi đại diện cho Action - DEFAULT
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Ngoài ra, Action còn có một thuộc tính kiểu boolean để bạn có thể enable hay disable một action Khi bạn muốn set thuộc tính cho Action bạn dùng phương thức putValue(String key, Object obj); key ở đây là một trong các hằng số ở trên, một Hashtable sẽ được dùng để lưu giữ các giá trị trên. Ví dụ khi bạn muốn add một icon: putValue(Action.SMALL_ICON, new ImageIcon(...)); hoặc bạn muốn add một tooltip: putValue(Action.SHORT_DESCRIPTION, “Tooltip”); Ngược lại, bạn dùng phương thức: getValue(String key); để lấy về giá trị tương ứng với hằng số ở trên. Phương thức này trả về một Object, vì vậy bạn phải ép kiểu để có được giá trị mong muốn. AbstractAction AbstractAction là lớp implements Action interface và đã định nghĩa sẵn cho bạn hầu hết các phương trong Action interface. Bạn chỉ cần kế thừa lớp này và định nghĩa lại phương thức actionPerformed(). Vậy là đủ rồi, chúng ta cùng áp dụng Actibạn có thể đặt tên gì cũng được. Trong lớp này, tôi tạo thêm 3 inner claon để xây dựng GUI cho chương trình. Tôi gọi chương trình là NotepadForBoss, ss - FileAction - EditAction - HelpAction package org.mountain.abstractaction; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JToolBar; import javax.swing.KeyStroke; public class NotepadForBoss extends JFrame { private JMenuBar menuBar; private JToolBar toolBar; private JTextArea display; private JMenu fileMenu, editMenu, helpMenu; private FileAction newAction, openAction, saveAction, exitAction; private EditAction copyAction, cutAction, pasteAction;
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. private HelpAction contentsAction, aboutAction; //.................................................................. // This action for File menu class FileAction extends AbstractAction { private String name; private Icon icon; public FileAction(String name) { super(name); // this.name = name; // this.putValue(AbstractAction.NAME, name); // this.putValue(AbstractAction.SHORT_DESCRIPTION, name); } public FileAction(String name, Icon icon) { super(name, icon); // this(name); // this.icon = icon; // if(icon != null) { // putValue(AbstractAction.SMALL_ICON, icon); // } } public FileAction(String name, Icon icon, KeyStroke key) { this(name, icon); putValue(AbstractAction.ACCELERATOR_KEY, key); } public void actionPerformed(ActionEvent e) { display.setText("FileAction --- You just pressed: " + (String)getValue(AbstractAction.NAME)); } } // This action for Edit menu class EditAction extends AbstractAction { private String name; private Icon icon; public EditAction(String name) { this.name = name; this.putValue(AbstractAction.NAME, name); } public EditAction(String name, Icon icon) { this(name);
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. this.icon = icon; if(icon != null) { putValue(AbstractAction.SMALL_ICON, icon); } } public EditAction(String name, Icon icon, KeyStroke key) { this(name, icon); putValue(AbstractAction.ACCELERATOR_KEY, key); } public void actionPerformed(ActionEvent e) { display.setText("EditAction --- You just pressed: " + (String)getValue(AbstractAction.NAME)); } } // This action for Help menu class HelpAction extends AbstractAction { private String name; private Icon icon; public HelpAction(String name) { this.name = name; this.putValue(AbstractAction.NAME, name); } public HelpAction(String name, Icon icon) { this(name); this.icon = icon; if(icon != null) { putValue(AbstractAction.SMALL_ICON, icon); } } public HelpAction(String name, Icon icon, KeyStroke key) { this(name, icon); putValue(AbstractAction.ACCELERATOR_KEY, key); } public void actionPerformed(ActionEvent e) { String name = (String)getValue(AbstractAction.NAME); if("About".equalsIgnoreCase(name)) { JOptionPane.showMessageDialog(null, "Hello!"); } else { display.setText("HelpAction --- You just pressed: " + (String)getValue(AbstractAction.NAME)); } } } }
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Giờ đến lúc ta tạo menu bar và toolbar từ những lớp này. package org.mountain.abstractaction; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JToolBar; import javax.swing.KeyStroke; public class NotepadForBoss extends JFrame { private JMenuBar menuBar; private JToolBar toolBar; private JTextArea display; private JMenu fileMenu, editMenu, helpMenu; private FileAction newAction, openAction, saveAction, exitAction; private EditAction copyAction, cutAction, pasteAction; private HelpAction contentsAction, aboutAction; public NotepadForBoss() { super("Abstract Action Example v1.0"); setDefaultCloseOperation(EXIT_ON_CLOSE); menuBar = new JMenuBar(); toolBar = new JToolBar(); fileMenu = new JMenu("File"); newAction = new FileAction("New", new ImageIcon("new.gif"), KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK)); fileMenu.add(newAction); openAction = new FileAction("Open", new ImageIcon("open.gif"), KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK)); fileMenu.add(openAction); saveAction = new FileAction("Save", new ImageIcon("save.gif"), KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK)); fileMenu.add(saveAction);
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. exitAction = new FileAction("Exit"); fileMenu.addSeparator(); fileMenu.add(exitAction); editMenu = new JMenu("Edit"); copyAction = new EditAction("Copy", new ImageIcon("copy.gif")); editMenu.add(copyAction); cutAction = new EditAction("Cut", new ImageIcon("cut.gif")); editMenu.add(cutAction); pasteAction = new EditAction("Paste", new ImageIcon("paste.gif")); editMenu.add(pasteAction); helpMenu = new JMenu("Help"); contentsAction = new HelpAction("Contents"); helpMenu.add(contentsAction); aboutAction = new HelpAction("About", new ImageIcon("palette_select.gif")); helpMenu.addSeparator(); helpMenu.add(aboutAction); menuBar.add(fileMenu); menuBar.add(editMenu); menuBar.add(helpMenu); toolBar.add(newAction); toolBar.add(openAction); toolBar.add(saveAction); toolBar.addSeparator(); toolBar.add(copyAction); toolBar.add(cutAction); toolBar.add(pasteAction); // toolBar.addSeparator(); // toolBar.addSeparator(); // toolBar.add(aboutAction); setJMenuBar(menuBar); add(toolBar, BorderLayout.NORTH); display = new JTextArea(); JScrollPane pane = new JScrollPane(display); getContentPane().add(pane, BorderLayout.CENTER); setSize(400, 300); } // This action for File menu class FileAction extends AbstractAction { //.................... }
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. // This action for Edit menu class EditAction extends AbstractAction { //.......................... } // This action for Help menu class HelpAction extends AbstractAction { //............................. } public static void main(String[] args) { JFrame f = new NotepadForBoss(); f.setVisible(true); } } Trong mỗi lớp Action ở trên chúng ta đã tạo ra 3 constructor. Thứ nhất là tạo action với tên: FileAction(String name); Thứ 2: tên cộng với một icon FileAction(String name, Icon icon); Thứ 3: ta thêm vào một tham số là phím (tổ hợp phím) tăng tốc FileAction(String name, Icon icon, KeyStroke keyStroke); Khi bạn chọn menu item hay click vào button, chương trình chỉ đơn giản in ra tên của action. Đây là GUI mà chúng ta đã tạo được:
- Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only. Action thực sự hữu dụng khi bạn làm việc với JMenu, JToolBar, hoặc là JPopupMenu. Rõ ràng là bạn không cần phải làm công việc nhàm chán, tạo menu item, add cho nó một ActionListener, rồi add nó vào một menu. Bạn chỉ cần add một action vào menu. Có điều ứng dụng của chúng ta chưa hoàn chỉnh cho lắm, hình như thiếu vài cái menu. Tôi để công việc này lại cho bạn... Hãy lấy điểm với sếp của bạn nhé.
CÓ THỂ BẠN MUỐN DOWNLOAD
Chịu trách nhiệm nội dung:
Nguyễn Công Hà - Giám đốc Công ty TNHH TÀI LIỆU TRỰC TUYẾN VI NA
LIÊN HỆ
Địa chỉ: P402, 54A Nơ Trang Long, Phường 14, Q.Bình Thạnh, TP.HCM
Hotline: 093 303 0098
Email: support@tailieu.vn