- Bài 1: Tổng quan ngôn ngữ Java
- Bài 2: Hướng dẫn cài đặt và cấu hình Java
- Bài 3: Hướng dẫn cài đặt và cấu hình Intellij IDEA trên Window
- Bài 4: Tạo Project và làm quen với Intelij IDEA
- Bài 5: Cú pháp và quy tắc cơ bản trong Java
- Bài 6: Các kiểu dữ liệu trong Java
- Bài 7: Các kiểu biến trong Java
- Bài 8: Toán tử trong Java
- Bài 9: Hệ thống Unicode trong Java
- Bài 10: Các kiểu vòng lặp
- Bài 11: Câu lệnh điều khiển rẽ nhánh
- Bài 12: Câu lệnh Break, Continue trong Java
- Bài 13: Lớp và đối tượng
- Bài 14: Tính chất của lập trình hướng đối tượng trong Java
- Bài 15: Abstract class và Interface trong Java
- Bài 16: Từ khóa super và this trong Java
- Bài 17: Từ khóa static và final trong Java
- Bài 18: Mảng (Array) trong Java
- Bài 19: Package trong Java
- Bài 21: String trong Java
- Bài 22: StringBuffer và StringBuilder
- Bài 23: Tổng quan về File và I/O
- Bài 24: Xử lý nhập xuất bằng Byte Stream và Character Stream
- Bài 25: Thao tác với tệp và thư mục trong Java
- Bài 26: Tổng quan về Collection trong Java
- Bài 27: Những Interface phổ biến trong Java Collection Framework
- Bài 28: Những Class được triển khai dựa trên Interface của Java Collection
- Bài 29: Khái niệm xử lý ngoại lệ trong Java
- Bài 30: Hướng dẫn xử lý ngoại lệ trong Java
- Bài 31: Đa luồng trong Java
- Bài 32: Thread synchronization trong Java
- Bài 33: Tổng quan về Java AWT
- Bài 34: Container trong Java AWT
- Bài 35: Component trong Java AWT
- Bài 36: Layout Manager trong Java AWT
- Bài 37: Xử lý sự kiện trong Java AWT
- Bài 38: Tổng quan về Java Swing
- Bài 39: Container trong Java Swing
- Bài 40: Component trong Java Swing
- Bài 41: Layout trong Java Swing
- Bài 42: Event trong Java Swing
- Bài 43: Menu trong Java Swing
- Bài 44: Kết nối cơ sở dữ liệu với thư viện JDBC trong Java
Bài 42: Event trong Java Swing - Lập trình Java cơ bản
Đăng bởi: Admin | Lượt xem: 10386 | Chuyên mục: Java
Event (sự kiện) là một phần quan trọng của bất kỳ ứng dụng GUI nào. Tất cả các ứng dụng dạng GUI xử lý event trong suốt thời gian mà nó chạy. Event phần lớn được tạo ra bởi người dùng, nhưng cũng có lúc được tạo ra bởi chính ứng dụng. Có ba thành phần tham gia vào hệ thống event:
- Event nguồn
- Đối tượng event
- Đối tượng lắng nghe event
Event nguồn là đối tượng tạo ra sự thay đổi. Cứ có gì đó trong ứng dụng tạo ra sự thay đổi nào đó thì nó chính là event nguồn. Đối tượng event là chính bản thân cái event đó đã được mã hóa. Đối tượng lắng nghe event làm công việc xử lý event đó.
1. Đối tượng Event
Mỗi khi có thứ gì đó xảy ra thì một đối tượng event sẽ được tạo. Chẳng hạn như khi bạn click vào một button hay chọn một item trong một danh sách. Đối tượng event lưu trữ thông tin về loại sự kiện đã xảy ra. Chúng ta sẽ xem xét thông tin đó trong ví dụ dưới đây.
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JList;
public class EventObjectEx extends JFrame {
private JList list;
private DefaultListModel model;
public EventObjectEx() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
model = new DefaultListModel();
list = new JList(model);
list.setMinimumSize(new Dimension(250, 150));
list.setBorder(BorderFactory.createEtchedBorder());
JButton okButton = new JButton("OK");
okButton.addActionListener(new ClickAction());
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(okButton)
.addGap(20)
.addComponent(list)
);
gl.setVerticalGroup(gl.createParallelGroup()
.addComponent(okButton)
.addComponent(list)
);
pack();
setTitle("Event Example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class ClickAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
Locale locale = Locale.getDefault();
Date date = new Date(e.getWhen());
String tm = DateFormat.getTimeInstance(DateFormat.SHORT,
locale).format(date);
if (!model.isEmpty()) {
model.clear();
}
if (e.getID() == ActionEvent.ACTION_PERFORMED) {
model.addElement("Event Id: ACTION_PERFORMED");
}
model.addElement("Time: " + tm);
String source = e.getSource().getClass().getName();
model.addElement("Source: " + source);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
EventObjectEx ex = new EventObjectEx();
ex.setVisible(true);
}
});
}
}
Trong ví dụ này chúng ta tạo một button và một list, list sẽ hiển thị các thông tin về đối tượng event được gây ra bởi button.
1okButton.addActionListener(newClickAction());
Lớp ClickAction lắng nghe sự kiện từ button OK.
private class ClickAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
...
}
}
Phương thức actionPerformed() được gọi mỗi lần sự kiện xảy ra, phương thức này nhận tham số là một đối tượng ActionEvent.
Locale locale = Locale.getDefault();
Date date = new Date(e.getWhen());
String s = DateFormat.getTimeInstance(DateFormat.SHORT,
locale).format(date);
Chúng ta có thể lấy thời điểm event xảy ra từ phương thức getWhen(), thời gian trong phương thức này tính theo mili giây nên chúng ta phải định dạng lại cho phù hợp.
String source = e.getSource().getClass().getName();
model.addElement("Source: " + source);
Chúng ta có thể lấy được thông tin về đối tượng gây ra event từ phương thức getSource() và một số thông tin bên trong lớp đó.
2. Tạo đối tượng lắng nghe sự kiện
Có 3 cách để tạo một đối tượng lắng nghe sự kiện trong Java Swing.
- Tạo lớp ẩn nội (Anonymous Inner class)
- Tạo lớp nội (Inner class)
- Tạo lớp kế thừa (Derived class)
Tạo lớp ẩn nội
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class AnonymousInnerClassEx extends JFrame {
public AnonymousInnerClassEx() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
JButton closeButton = new JButton("Close");
closeButton.setBounds(40, 50, 80, 25);
closeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(220)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(180)
);
pack();
setTitle("Event Example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
AnonymousInnerClassEx ex =
new AnonymousInnerClassEx();
ex.setVisible(true);
}
});
}
}
Trong ví dụ này chúng ta tạo một đối tượng lắng nghe sự kiện từ một button.
JButton closeButton = new JButton("Close");
Khi click button thì thoát chương trình.
closeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
Để gắn một đối tượng lắng nghe vào một component thì chúng ta dùng phương thức addActionListener(). Ở đây chúng ta dùng lớp “ẩn nội”, nếu bạn chưa biết thì tức là tạo một đối tượng và code các phương thức trừu tượng ngay bên trong một phương thức khác.
Tạo lớp nội
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class InnerClassExample extends JFrame {
public InnerClassExample() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
JButton closeButton = new JButton("Close");
ButtonCloseListener listener = new ButtonCloseListener();
closeButton.addActionListener(listener);
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(220)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(180)
);
pack();
setTitle("Event Example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class ButtonCloseListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
InnerClassExample ex = new InnerClassExample();
ex.setVisible(true);
}
});
}
}
Ví dụ này cũng giống ví dụ trên, chỉ khác là chúng ta dùng lớp “nội”: định nghĩa một lớp bên trong một lớp khác, tuy nhiên các lớp này phải được implements từ lớp ActionListener.
private class ButtonCloseListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
Tạo lớp kế thừa
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class DerivedClassExample extends JFrame {
public DerivedClassExample() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
MyButton closeButton = new MyButton("Close");
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(220)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addGap(180)
);
pack();
setTitle("Event Example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class MyButton extends JButton
implements ActionListener {
public MyButton(String text) {
super.setText(text);
addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
DerivedClassExample ex = new DerivedClassExample();
ex.setVisible(true);
}
});
}
}
Trong ví dụ này chúng ta cũng tạo một button có chức năng thoát chương trình, nhưng ở đây chúng ta tạo một lớp kế thừa từ lớp JButton là implements sẵn giao diện ActionListener. Tức là bản thân lớp này đã tự động lắng nghe các sự kiện click rồi, không cần phải dùng đến phương thức addActionListener() như với lớp ẩn nội nữa.
private class MyButton extends JButton
implements ActionListener {
public MyButton(String text) {
super.setText(text);
addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
3. Gắn một listener vào nhiều component
Một listener có thể lắng nghe từ nhiều component khác nhau.
Ví dụ:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MultipleSources extends JFrame {
private JLabel statusbar;
public MultipleSources() {
initUI();
}
private void initUI() {
JPanel panel = new JPanel();
GroupLayout gl = new GroupLayout(panel);
panel.setLayout(gl);
statusbar = new JLabel("Ready");
statusbar.setBorder(BorderFactory.createEtchedBorder());
ButtonListener butlist = new ButtonListener();
JButton closeButton = new JButton("Close");
closeButton.addActionListener(butlist);
JButton openButton = new JButton("Open");
openButton.addActionListener(butlist);
JButton findButton = new JButton("Find");
findButton.addActionListener(butlist);
JButton saveButton = new JButton("Save");
saveButton.addActionListener(butlist);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(closeButton)
.addComponent(openButton)
.addComponent(findButton)
.addComponent(saveButton)
.addGap(250)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(closeButton)
.addComponent(openButton)
.addComponent(findButton)
.addComponent(saveButton)
.addGap(20)
);
gl.linkSize(closeButton, openButton,
findButton, saveButton);
add(panel, BorderLayout.CENTER);
add(statusbar, BorderLayout.SOUTH);
pack();
setTitle("Event Example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton o = (JButton) e.getSource();
String label = o.getText();
statusbar.setText(" " + label + " button clicked");
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MultipleSources ms = new MultipleSources();
ms.setVisible(true);
}
});
}
}
4. Gắn nhiều listener vào một component
Nếu có thể dùng một listener cho nhiều component thì cũng có thể gắn nhiều listener vào một component.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.CENTER;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import static javax.swing.GroupLayout.PREFERRED_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
public class MultipleListeners extends JFrame {
private JLabel statusbar;
private JSpinner spinner;
private int count = 0;
public MultipleListeners() {
initUI();
}
private void initUI() {
JPanel panel = new JPanel();
GroupLayout gl = new GroupLayout(panel);
panel.setLayout(gl);
add(panel, BorderLayout.CENTER);
statusbar = new JLabel("0");
statusbar.setBorder(BorderFactory.createEtchedBorder());
add(statusbar, BorderLayout.SOUTH);
JButton addButton = new JButton("+");
addButton.addActionListener(new ButtonListener1());
addButton.addActionListener(new ButtonListener2());
Calendar calendar = Calendar.getInstance();
int currentYear = calendar.get(Calendar.YEAR);
SpinnerModel yearModel = new SpinnerNumberModel(currentYear,
currentYear - 100,
currentYear + 100,
1);
spinner = new JSpinner(yearModel);
spinner.setEditor(new JSpinner.NumberEditor(spinner, "#"));
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addComponent(addButton)
.addGap(20)
.addComponent(spinner, DEFAULT_SIZE,
DEFAULT_SIZE, PREFERRED_SIZE)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addGroup(gl.createParallelGroup(CENTER)
.addComponent(addButton)
.addComponent(spinner, DEFAULT_SIZE,
DEFAULT_SIZE, PREFERRED_SIZE))
);
pack();
setTitle("Event Example");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class ButtonListener1 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Integer val = (Integer) spinner.getValue();
spinner.setValue(++val);
}
}
private class ButtonListener2 implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
statusbar.setText(Integer.toString(++count));
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MultipleListeners ml = new MultipleListeners();
ml.setVisible(true);
}
});
}
}
Trong ví dụ này chúng ta tạo một button, một spinner và một statusbar. Chúng ta định nghĩa 2 listener và gắn cả hai listener này vào button, một listener sẽ thay đổi giá trị trên spinner, một listener sẽ thay đổi đoạn text trong statusbar.
5. Xử lý sự kiện di chuyển
Trong ví dụ này chúng ta tìm hiểu về cách bắt sự kiện có liên quan đến sự hiện diện của component.
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MovingWindowEx extends JFrame
implements ComponentListener {
private JLabel labelx;
private JLabel labely;
public MovingWindowEx() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
addComponentListener(this);
labelx = new JLabel("x: ");
labelx.setFont(new Font("Serif", Font.BOLD, 14));
labelx.setBounds(20, 20, 60, 25);
labely = new JLabel("y: ");
labely.setFont(new Font("Serif", Font.BOLD, 14));
labely.setBounds(20, 45, 60, 25);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(labelx)
.addComponent(labely)
.addGap(250)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(labelx)
.addComponent(labely)
.addGap(130)
);
pack();
setTitle("Event Example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
@Override
public void componentResized(ComponentEvent e) {
}
@Override
public void componentMoved(ComponentEvent e) {
int x = e.getComponent().getX();
int y = e.getComponent().getY();
labelx.setText("x: " + x);
labely.setText("y: " + y);
}
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MovingWindowEx ex = new MovingWindowEx();
ex.setVisible(true);
}
});
}
}
6. Sử dụng lớp Adapter thay thế cho Listener
Trong ví dụ trên chúng ta implement giao diện ComponentListener và phải override toàn bộ các phương thức ảo trong giao diện này, như thế rất khó chịu, chính vì thế và Java đã tạo ra các lớp adapter. Adapter đơn giản là các lớp đã implement sẵn các lớp listener tương ứng và override toàn bộ phương thức ảo trước rồi. Vì thế nên khi dùng adapter chúng ta chỉ cần dùng các phương thức mà chúng ta muốn thôi.
Ví dụ:
- Giao diện ComponentListener bắt buộc bạn phải override các phương thức ảo componentResized(), componentMoved(), componentShown(), và componentHidden() mặc dù bạn không muốn.
- Lớp ComponentAdapter đã implement sẵn giao diện ComponentListener và override toàn bộ các phương thức ảo trên rồi, bạn chỉ cần override lại phương thức mà bạn muốn.
Ví dụ dưới đây giống như ví dụ ở trên, chỉ khác là chúng ta dùng lớp ComponentAdapter.
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class AdapterExample extends JFrame {
private JLabel labelx;
private JLabel labely;
public AdapterExample() {
initUI();
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
addComponentListener(new MoveAdapter());
labelx = new JLabel("x: ");
labelx.setFont(new Font("Serif", Font.BOLD, 14));
labely = new JLabel("y: ");
labely.setFont(new Font("Serif", Font.BOLD, 14));
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(labelx)
.addComponent(labely)
.addGap(250)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(labelx)
.addComponent(labely)
.addGap(130)
);
pack();
setTitle("Event Example");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private class MoveAdapter extends ComponentAdapter {
@Override
public void componentMoved(ComponentEvent e) {
int x = e.getComponent().getX();
int y = e.getComponent().getY();
labelx.setText("x: " + x);
labely.setText("y: " + y);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
AdapterExample ex = new AdapterExample();
ex.setVisible(true);
}
});
}
}
Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!
- Bài 1: Tổng quan ngôn ngữ Java
- Bài 2: Hướng dẫn cài đặt và cấu hình Java
- Bài 3: Hướng dẫn cài đặt và cấu hình Intellij IDEA trên Window
- Bài 4: Tạo Project và làm quen với Intelij IDEA
- Bài 5: Cú pháp và quy tắc cơ bản trong Java
- Bài 6: Các kiểu dữ liệu trong Java
- Bài 7: Các kiểu biến trong Java
- Bài 8: Toán tử trong Java
- Bài 9: Hệ thống Unicode trong Java
- Bài 10: Các kiểu vòng lặp
- Bài 11: Câu lệnh điều khiển rẽ nhánh
- Bài 12: Câu lệnh Break, Continue trong Java
- Bài 13: Lớp và đối tượng
- Bài 14: Tính chất của lập trình hướng đối tượng trong Java
- Bài 15: Abstract class và Interface trong Java
- Bài 16: Từ khóa super và this trong Java
- Bài 17: Từ khóa static và final trong Java
- Bài 18: Mảng (Array) trong Java
- Bài 19: Package trong Java
- Bài 21: String trong Java
- Bài 22: StringBuffer và StringBuilder
- Bài 23: Tổng quan về File và I/O
- Bài 24: Xử lý nhập xuất bằng Byte Stream và Character Stream
- Bài 25: Thao tác với tệp và thư mục trong Java
- Bài 26: Tổng quan về Collection trong Java
- Bài 27: Những Interface phổ biến trong Java Collection Framework
- Bài 28: Những Class được triển khai dựa trên Interface của Java Collection
- Bài 29: Khái niệm xử lý ngoại lệ trong Java
- Bài 30: Hướng dẫn xử lý ngoại lệ trong Java
- Bài 31: Đa luồng trong Java
- Bài 32: Thread synchronization trong Java
- Bài 33: Tổng quan về Java AWT
- Bài 34: Container trong Java AWT
- Bài 35: Component trong Java AWT
- Bài 36: Layout Manager trong Java AWT
- Bài 37: Xử lý sự kiện trong Java AWT
- Bài 38: Tổng quan về Java Swing
- Bài 39: Container trong Java Swing
- Bài 40: Component trong Java Swing
- Bài 41: Layout trong Java Swing
- Bài 42: Event trong Java Swing
- Bài 43: Menu trong Java Swing
- Bài 44: Kết nối cơ sở dữ liệu với thư viện JDBC trong Java