Các component của Swing, bạn có thể nhận ra rằng chúng được thiết kế để tách riêng hai phần giao diện và dữ liệu. Cụ thể hơn các thành phần này được thiết kế dựa trên mô hình MVC (Model-View-Controller). Việc áp dụng mô hình này giúp cho việc quản lý dữ liệu và thay đổi giao diện của các component hiệu quả hơn.
Mô hình MVC
Một ứng dụng thiết kế theo mô hình MVC sẽ được chia thành 3 phần tương ứng như hình sau:
– Model: lưu trữ hoặc làm cầu nối với dữ liệu.
– View: hiển thị giao diện và nhận các thông điệp người dùng. View có thể truy vấn dữ liệu từ Model để hiển thị lên màn hình.
– Controller: làm trung gian chuyển các thông điệp người dùng từ View đến Model và cập nhật lại View khi cần thiết.
Trong Swing, theo quy mô của component, mô hình được thay đổi để phù hợp cho việc áp dụng cho các component. Cụ thể phần View và Controller sẽ được gộp chung lại trong một UI Object.
Trong hình minh họa trên, UI Manager được dùng để quản lý giao diện của các component (tính năng look and feel).
GUI-state Model và Application-data Model
Tất cả component trong Swing đều sử dụng một trong hai mô hình là GUI-state hoặc Application-data.
- GUI-state: lưu giữ trạng thái của component, ví dụ như button có được nhấn xuông hay không, phần tử nào được chọn trong một list,…
- Application-data: chứa dữ liệu để hiển thị lên component. Dữ liệu này thường nằm ở mức ứng dụng như một table, danh sách phần tử của list.
Không phải tất cả component đều phân biệt rõ ràng mô hình được sử dụng. Ví dụ như JSlider và JprogressBar. Bạn có thể nhận thấy điều này trong bảng liệt kê mô hình mà các component của Swing sử dụng sau:
Component
Model Interface
Model Type
JButton
ButtonModel
GUI
JToggleButton
ButtonModel
GUI/data
JCheckBox
ButtonModel
GUI/data
JRadioButton
ButtonModel
GUI/data
JMenu
ButtonModel
GUI
JMenuItem
ButtonModel
GUI
JCheckBoxMenuItem
ButtonModel
GUI/data
JRadioButtonMenuItem
ButtonModel
GUI/data
JComboBox
ComboBoxModel
data
JProgressBar
BoundedRangeModel
GUI/data
JScrollBar
BoundedRangeModel
GUI/data
JSlider
BoundedRangeModel
GUI/data
JTabbedPane
SingleSelectionModel
GUI
JList
ListModel
data
JList
ListSelectionModel
GUI
JTable
TableModel
data
JTable
TableColumnModel
GUI
JTree
TreeModel
data
JTree
TreeSelectionModel
GUI
JEditorPane
Document
data
JTextPane
Document
data
JTextArea
Document
data
JTextField
Document
data
JPasswordField
Document
data
Thông báo sự thay đổi của Model
Việc thông báo khi model của các component thay đổi là một điều cần thiết để cập nhật lại các trạng thái, giao diện của các đối tượng liên quan. Swing cung cấp hai cách thức để làm điều này:
- Lightweight: thông báo sự thay đổi trạng thái của model. Sự kiện được sử dụng cho kiểu thông báo này là ChangeEvent. Cách này được dùng cho những component đơn giản và có thể quản lý nhiều thay đổi của model trong một sự kiện.
Ví dụ:
checkbox.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JCheckBox checkbox=(JCheckBox)e.getSource(); DefaultButtonModel model = (DefaultButtonModel)checkbox.getModel(); System.out.println("Selected: "+model.isSelected()); } });
- Stateful: Sử dụng cho các component phức tạp và cho mỗi sự thay đổi cụ thể.
Ví dụ:
String items[] = {"One", "Two", "Three", "Four"}; JList<String> list = new JList<String>(items); this.add(list); list.addListSelectionListener (new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { JList list=(JList)e.getSource(); ListSelectionModel model=(ListSelectionModel)list.getSelectionModel(); if (!e.getValueIsAdjusting()) { System.out.println("Selection index: " + model.getLeadSelectionIndex()); } } });
Tạo Custom Model
Ví dụ sau tạo một custom model cho JList bằng cách tạo một lớp con của lớp AbstractListModel. Khi kế thừa lớp abtract này, cần hiện thực hai phương thức là getElementAt(index) và getSize().
import java.awt.Dimension; import java.awt.FlowLayout; import javax.swing.AbstractListModel; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; class MyListModel extends AbstractListModel { String[] data = { "1st","2nd","3rd","4th" }; public Object getElementAt(int index) { return "Item "+data[index]; } public int getSize() { return data.length-1; } } public class CustomModelDemo extends JFrame { public CustomModelDemo(){ super("Custom Model Demo"); setLayout(new FlowLayout()); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocationRelativeTo(null); setSize(300, 200); JList<String> list = new JList<String>(new MyListModel()); list.setPreferredSize(new Dimension(80, 100)); list.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if(!e.getValueIsAdjusting()) { JList list=(JList)e.getSource(); System.out.println(list.getSelectedValue()); } } }); add(list); } public static void main(String[] a){ new CustomModelDemo().setVisible(true); } }
Bạn có thể thấy ảnh hưởng của lớp MyListModel trong ví dụ trên đến việc hiển thị dữ liệu lên trên JList khi chạy ví dụ.
Cụ thể:
– Trong phương thức getElementAt() được dùng để lấy giá trị của một phần tử tại vị trí xác định, tôi sẽ nối thêm chuỗi “Item “ phía trước.
– Bất kì JList khi sử dụng model này đã có sẵn dữ liệu mà không cần thêm vào. Dữ liệu này chính là mảng String[] data trong lớp MyListModel.
– Mặc dù mảng data có 4 phần tử nhưng khi hiển thị lên JList chỉ có 3 phần tử, nguyên nhân là do phương thức getSize() trả về giá trị data.length-1.
https://yinyangit.wordpress.com
Tóm Tắt
Đánh giá:
Share this:
Thích bài này:
Thích
Đang tải…