Java Swing – Ví dụ mở đầu

4.1/5 - (32 votes)

Trong bài này chúng ta sẽ viết một số chương trình nhỏ để làm quen với Swing.

Ví dụ 1

Trong ví dụ dưới đây chúng ta sẽ hiển thị một cửa sổ lên màn hình.

import java.awt.EventQueue;
import javax.swing.JFrame;

public class SimpleEx extends JFrame {

    public SimpleEx() {

        initUI();
    }

    private void initUI() {
        
        setTitle("Simple example");
        setSize(300, 200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
        
            @Override
            public void run() {
                SimpleEx ex = new SimpleEx();
                ex.setVisible(true);
            }
        });
    }
}

Bạn có thể thay đổi kích thước, phóng to, thu nhỏ cửa sổ bằng chuột… mặc định thì những thứ như thế phải code rất nhiều nếu bạn dùng thư viện của hệ thống (như Windows API viết bằng C), tuy nhiên ở đây Swing tự động làm các công việc đó cho bạn rồi nên đoạn code ở trên khá đơn giản.

public class SimpleEx extends JFrame {

Lớp SimpleEx được kế thừa từ component JFrame, đây là một component đặc biệt dùng để chứa các component khác.

Lưu ý: các lớp tạo nên toàn bộ mọi thứ trong swing có tên chung là Component, tiếng việt có nghĩa là thành phần, nhưng trong series này mình sẽ không dùng tiếng việt mà dùng từ component luôn.

public SimpleEx() {

    initUI();
}

Theo kinh nghiệm lập trình của mình thì tốt nhất là chúng ta không nên để các đoạn code trong phương thức khởi tạo mà nên di chuyển chúng ta một phương thức khác dành riêng cho từng loại công việc.

setTitle("Simple example");

Phương thức setTitle() sẽ thay đổi tiêu đề của cửa sổ.

setSize(300, 200);

Phương thức setSize() thay đổi kích thước cửa sổ.

setLocationRelativeTo(null);

Dòng code trên có tác dụng hiển thị cửa sổ lên vị trí giữa màn hình.

setDefaultCloseOperation(EXIT_ON_CLOSE);

Dòng code trên thiết lập việc tắt chương trình khi click nào nút X trên thanh tiêu đề. Nếu bạn không thêm dòng đó vào thì khi bạn bấm nút X, cửa sổ chương trình vẫn sẽ biến mất nhưng bản thân chương trình thì vẫn chạy ngầm bên dưới chứ không tắt hẳn.

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        SimpleExample ex = new SimpleExample();
        ex.setVisible(true);
    }
});

Phương thức invokeLater() sẽ chạy ứng dụng của chúng ta trong một luồng do EventQueue quản lý. Thực ra bạn cũng không cần đến EventQueue làm gì, chỉ cần tạo một đối tượng BasicEx rồi setVisible(true) là có thể chạy được nhưng trên tài liệu của Oracle thì lại khuyên chúng ta đặt bên trong EventQueue vì lý do là làm như vậy sẽ đảm bảo an toàn cho ứng dụng (mình cũng không hiểu tại sao) nên thôi thì mình cứ làm vậy 🙂

Capture

Ví dụ 2

Trong ví dụ này, chúng ta sẽ làm việc với Button.

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.JComponent;
import javax.swing.JFrame;

public class QuitButtonEx extends JFrame {

    public QuitButtonEx() {

        initUI();
    }

    private void initUI() {

        JButton quitButton = new JButton("Quit");

        quitButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                System.exit(0);
            }
        });

        createLayout(quitButton);

        setTitle("Quit button");
        setSize(300, 200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private void createLayout(JComponent... arg) {

        Container pane = getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);

        gl.setAutoCreateContainerGaps(true);

        gl.setHorizontalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
        );

        gl.setVerticalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
        );
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
        
            @Override
            public void run() {
                QuitButtonEx ex = new QuitButtonEx();
                ex.setVisible(true);
            }
        });
    }
}

Chúng ta đặt một JButton lên cửa sổ và gắn một ActionListener vào button này.

JButton quitButton = new JButton("Quit");

Dòng code trên tạo một đối tượng JButton với tham số là đoạn text hiển thị trên button đó.

quitButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent event) {
        System.exit(0);
    }
});

Chúng ta gắn một ActionListener vào button, phương thức actionPerformed() sẽ được gọi mỗi lần chúng ta click vào button, bên trong phương thức chúng ta gọi System.exit() để thoát chương trình.

createLayout(quitButton);

Khi các component con được tạo xong thì chúng ta tiến hành đưa chúng lên cửa sổ chính, tại đây mình chuyển đoạn code làm công việc đó qua phương thức createLayout().

Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);

Khu vực bên trong khung cửa sổ JFrame được gọi là pane hoặc panel, đây là vùng để chúng ta đặt các component vào đó. Vùng này được quản lý bởi các đối tượng layout (chúng ta sẽ tìm hiểu về quản lý Layout trong các bài viết sau), mặc định thì lớp layout chính quản lý cửa sổ khi mới tạo ra là BorderLayout, các chức năng của lớp này rất hạn chế nên ở đây mình dùng đến lớp GroupLayout.

gl.setAutoCreateContainerGaps(true);

Phương thức setAutoCreateContainerGaps() sẽ tự động tạo các khoảng trống phù hợp giữa các component và giữa các component với khung cửa sổ.

private void createLayout(JComponent... arg)
{
...
}

Lưu ý ở đây mình dùng cú pháp varargs để truyền tham số vào phương thức, cú pháp này cho phép chúng ta truyền vào số lượng tham số bất kỳ. Trong cú pháp này, tên của kiểu dữ liệu sẽ có 3 dấu chấm đằng sau nó, biến truyền vào sẽ trở thành một mảng. Bạn có thể tìm hiểu thêm về cú pháp varargs tại đây.

gl.setHorizontalGroup(gl.createSequentialGroup()
        .addComponent(quitButton)
);

gl.setVerticalGroup(gl.createSequentialGroup()
        .addComponent(quitButton)
);

GroupLayout sắp xếp các component theo chiều ngang và chiều dọc của cửa sổ. Nhưng ở đây chúng ta chỉ có một component là JButton nên cũng chưa thấy nhiều tiện ích cho lắm.

Capture

Ví dụ 3

Trong ví dụ này chúng ta sẽ cho hiển thị tooltip.

import java.awt.EventQueue;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class TooltipEx extends JFrame {

    public TooltipEx() {
        
        initUI();
    }

    private void initUI() {

        JButton btn = new JButton("Button");
        btn.setToolTipText("A button component");

        createLayout(btn);
        
        setTitle("Tooltip");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    private void createLayout(JComponent... arg) {
        
        JPanel pane = (JPanel) getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);
        
        pane.setToolTipText("Content pane");        
        
        gl.setAutoCreateContainerGaps(true);
        
        gl.setHorizontalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
                .addGap(200)
        );

        gl.setVerticalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
                .addGap(120)
        );
        
        pack();        
    }

    public static void main(String[] args) {
        
        EventQueue.invokeLater(new Runnable() {
        
            @Override
            public void run() {
                TooltipEx ex = new TooltipEx();
                ex.setVisible(true);
            }
        });
    }
}

Tooltip là các đoạn text mô tả được hiện lên bên cạnh các component. Trong ví dụ này, mỗi khi di chuột vào button hoặc lên vùng trống của sổ, một tooltip sẽ hiện ra.

btn.setToolTipText("A button component");

Để cài đặt tooltip cho bất cứ component nào thì chúng ta dùng phương thức setTooltipText().

JPanel pane = (JPanel) getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);

Như đã nói ở trên, vùng trống trên cửa sổ được gọi là panel, để lấy đối tượng panel thì chúng ta dùng phương thức getContentPane(), tuy nhiên phương thức này trả về lớp Container, lớp này không có sẵn phương thức nào để làm việc với tooltip nên chúng ta chuyển đổi kiểu dữ liệu sang lớp JPanel.

Capture

pane.setToolTipText("Content pane");

Để tạo tooltip thì chỉ đơn giản là gọi phương thức setToolTipText() là được.

gl.setHorizontalGroup(gl.createSequentialGroup()
        .addComponent(arg[0])
        .addGap(200)
);

gl.setVerticalGroup(gl.createSequentialGroup()
        .addComponent(arg[0])
        .addGap(120)
);

Phương thức addGap() tạo khoảng trống xung quanh một đối tượng theo cả chiều ngang và chiều dọc.

pack();

Phương thức pack() sẽ tự động thay đổi kích thước của JFrame dựa trên kích thước của các component mà nó chứa kể cả các vùng được định nghĩa thêm như khoảng trống từ phương thức addGap().

Untitled

Ví dụ 4

Trong ví dụ này chúng ta sẽ tạo phím tắt cho các đối tượng, trong Java có hai cách thiết lập phím tắt cho đối tượng là dùng Mnemonics hoặc dùng KeyBinding, ở đây chúng ta sẽ dùng mnemonics.

import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;


public class MnemonicEx extends JFrame {
    
    public MnemonicEx() {
        
        initUI();
    }
    
    private void initUI() {
        
        JButton btn = new JButton("Button");
        btn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Button pressed");
            }
            
        });
        
        btn.setMnemonic(KeyEvent.VK_B);
        
        createLayout(btn);
        
        setTitle("Mnemonics");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);        
    }
    
    private void createLayout(JComponent... arg) {
        
        Container pane = getContentPane();
        GroupLayout gl = new GroupLayout(pane);
        pane.setLayout(gl);        

        gl.setAutoCreateContainerGaps(true);

        gl.setHorizontalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
                .addGap(200)
        );

        gl.setVerticalGroup(gl.createParallelGroup()
                .addComponent(arg[0])
                .addGap(200)
        );       

        pack();
    }        

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            
            @Override
            public void run() {
                MnemonicEx ex = new MnemonicEx();
                ex.setVisible(true);
            }
        });
    }
}

Chúng ta tạo một button và một listener gắn vào button đó, sau đó chúng ta thiết lập phím tắt cho button này là tổ hợp Alt+B.

btn.setMnemonic(KeyEvent.VK_B);

Phương thức setMnemonic() thiết lập phím tắt cho button, phương thức này mặc nhiên thiết lập phím tắt là phím Alt với phím do chúng ta chọn trong lớp KeyEvent.

5 5 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Inline Feedbacks
View all comments
Bùi Lực
Bùi Lực
6 năm trước

cho mình hỏi sao mình chạy ví dụ 3 mà nó không cho ra đoạn text Tooltip:”A button component” nhỉ?