You are on page 1of 67

Lập Trình GUI trong Java

TS. Lê Khánh Trình


Nội dung

1. Giao diện đồ họa người sử dụng


2. JavaFX
3. Các thành phần của JavaFX
4. UI Control
5. Layout Pane
6. Xử lý sự kiện
7. SceneBuilder
1
Giao diện đồ hoạ người dùng
(Graphics User Interface)
Giao diện đồ hoạ người dùng
● Graphical user interface - GUI
● Tạo các ứng dụng có giao diện đồ hoạ với các thành phần tương tác
trực tiếp với người dùng:
○ Button
○ Textbox, Label
○ Checkbox
○ List
○ …
Title bar
Ví dụ Textbox

Scroll
bar
Button
Lập trình GUI trong Java
● AWT
○ Java 1.0
● Swing
○ Nâng cấp các thành phần giao diện của AWT
○ Tích hợp trong Java 1.2
● JavaFX
○ Phát triển ứng dụng đa nền tảng (Desktop, mobile, TV, tablet
● Một số thư viện khác:
○ Eclipse’s Standard Widget Toolkit (SWT)
○ Google Web Toolkit (GWT)
○ …
So sánh giữa các thư viện
2
JavaFX
Một số tính năng của JavaFX
● Hỗ trợ FXML (tương tự HTML)

● Scene Builder: JavaFX cung cấp ứng dụng Scene Builder cho phép kéo

thả khi thiết kế

● Tương thích với Swing: có thể nhúng các thành phần Swing

● Built-in UI controls: cung cấp đa dạng controls

● CSS like styling: thiết kế giao diện với tính năng tương tự trong CSS
Tiện ích JavaFX trên IntellIj
3
Các thành phần của JavaFX
Stage, Scene, Node
Các thành phần giao diện JavaFX - Stage
Stage:
3 thành phần chính ● Là đối tượng lớp javafx.stage.Stage
● Chứa tất cả đối tượng khác của ứng dụng
JavaFX
● Bao gồm: Content Area (nội dung), Decoration
(tiêu đề và viền)
● Đối tượng stage được truyền như đối số cho
phương thức start() của lớp Application
● Tham số: width và height
● Phải gọi phương thức show() để hiển thị
Stage - styles
Có 5 styles cho Stage:

1. stage.initStyle(StageStyle.DECORATED);
2. stage.intStyle(StageStyle.UNDECORATED);
3. stage.initStyle(StageStyle.TRANSPARENT);
4. stage.initStyle(StageStyle.UNIFIED);
5. stage.initStyle(StageStyle.UTILITY);
Các thành phần giao diện JavaFX - Scene
Scene:
3 thành phần chính
● Là đối tượng lớp javafx.scene.Scene
● Chứa tất cả nội dung biểu diễn của một scene graph
● Mỗi Scene được thêm vào một Stage duy nhất
● Phương thức khởi tạo:
○ Scene (Parent root)
○ Scene (Parent root, double width, double height)
○ …
Scene Graph và Nodes
Scene Graph:
● Cấu trúc dữ liệu phân cấp cây
● Biểu diễn nội dung một Scene: controls và layout
Node:
● Là lớp cơ sở của các loại Node: javafx.scene.Node
● Biểu diễn đối tượng đồ hoạ của một Scene graph
○ Các phần tử hình học 2D hoặc 3D: Circle, Rectangle, Polygon, …
○ Phần tử tương tác: Button, Checkbox, TextArea, …
○ Phần tử đa phương tiện: Audio, Video, Image, …
Nodes
● Branch/Parent Node
○ Là node chứa các node con (lớp cơ sở là javafx.scene.Parent)
○ Group: chứa một list các node con được áp dụng cùng một hiệu ứng
chuyển đổi
○ Region: lớp cơ sở cho các UI Controls: Chart, Pane, Control
○ Webview: tương tự như Browser

● Leaf Node
○ node không có node con
○ Rectangle, Ellipse, Box, ImageView, MediaView
Cây phân cấp kế thừa Node
javafx.scene.Node

javafx.scene.Parent

javafx.scene.Group javafx.scene.layout.Region

javafx.scene.chart.Chart javafx.scene.layout.Pane javafx.scene.control.Control


Ví dụ

Sắp xếp các phần tử


để tạo bối cảnh

Nền trời
Tháp

Lan can Bụi cây Trăng


HelloWorld Example?

Thứ tự dựng giao


diện là gì
3.1
Ứng dụng JavaFX
Vòng đời ứng dụng
Các bước cài đặt phương thức start()
Vòng đời ứng dụng JavaFX
Bắt đầu khi một instance của một lớp thừa kế lớp Application
Khi gọi phương thức A.launch():

1. Tạo một instance của lớp A (A kế thừa lớp Application)


2. Gọi phương thức init()
3. Gọi phương thức start() với đối số là một stage
4. Ứng dụng kết thúc khi:
○ Đóng cửa sổ ứng dụng
○ Ứng dụng gọi Platform.exit() (Không dùng System.exit())
5. Gọi phương thức stop()
Cài đặt phương thức start()

1. Tạo một Scene graph với các Node

2. Tạo một Scene và thiết lập


3&4
2
3. Tạo một Stage, thêm Scene vào Stage 1

4. Hiển thị nội dung Stage


start() - 1. Tạo scene graph
1. Tạo root node trước, thêm nodes con sau
Group root = new Group();

//Retrieving the observable list object


ObservableList list = root.getChildren();

//Setting a node object as a node


list.add(NodeObject); 3&4
2
2. Tạo nodes con và thêm vào root sau
1

Group root = new Group(NodeObject);


start() - 2. Tạo scene

Tạo đối tượng Scene, bắt buộc phải truyền tham số là đối tượng root

Scene scene = new Scene(root);

3&4
Có thể tạo đối tượng Scene và thiết lập kèm theo
2
1
Scene scene = new Scene(root, 600, 300);
start() - 3 & 4. Tạo và hiển thị Stage
● Là tham số cho start() trong lớp Application, KHÔNG cần khởi tạo
public void start(Stage primaryStage) {

}

● Thao tác cơ bản:


3&4
//Đặt title Stage
primaryStage.setTitle("Sample application"); 2
1
//Cấu hình scene vào Stage
primaryStage.setScene(scene);

//Hiển thị stage


primaryStage.show();
Ví dụ: ứng dụng JavaFX rỗng
public class JavafxSample extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
//creating a Group object

//Creating a Scene

//setting color to the scene

//Setting the title to Stage.

//Adding the scene to Stage

//Displaying the contents of the stage

public static void main(String args[]) {


launch(args);
}
}

Viết code
Ví dụ: vẽ đường thẳng
public class DrawingLine extends Application{
@Override
public void start(Stage stage) {
//Creating a line object
Line line = new Line();

//Setting the properties to a line


line.setStartX(100.0); line.setStartY(150.0);
line.setEndX(500.0); line.setEndY(150.0);

Group root = new Group(line);


Scene scene = new Scene(root, 600, 300);
stage.setTitle("Sample application");
stage.setScene(scene);
stage.show();
}
public static void main(String args[]){
launch(args);
}
}
Ví dụ: hiển thị chữ

public class DecorationsExample extends Application {


@Override
public void start(Stage stage) {
//Creating a Text_Example object
Text text = new Text("Hi how are you");

//Setting font to the text


text.setFont(Font.font("verdana", FontWeight.BOLD,
FontPosture.REGULAR, 20));

//setting the position of the text


text.setX(50); text.setY(75);

//Striking through the text


text.setStrikethrough(true);

text2
4
JavaFX UI Control
JavaFX - UI Controls
Các thành phần chính của một giao diện người dùng

● UI elements: Phần tử người dùng tương tác (Button, Label,


Checkbox, …)

● Layouts: Nơi sắp xếp các UI elements trên màn hình

● Behavior: Tương tác của người dùng với UI elements trên layouts
(Event handling)
JavaFX - UI Controls
JavaFX - UI Controls
5
JavaFX Layout Pane
Layout Panes (Container Pane)

● Được sử dụng để sắp xếp các nodes


● Một số loại layouts phổ biến: HBox, VBox, Border Pane, Stack
Pane, Text Flow, Anchor Pane, Title Pane, Grid Pane, Flow Pane,

● Mỗi layout là một class kế thừa lớp Pane trong gói
javafx.layout
Các bước tạo Layout

● Tạo các nodes

● Khởi tạo đối tượng của lớp layout mong muốn

● Thiết lập các thuộc tính cho layout

● Thêm các nodes đã tạo vào layout


Layout HBox
● Sắp xếp các nodes theo hàng ngang
● Thuộc tính quan trọng:
○ alignment: căn hàng
○ spacing: khoảng cách giữa các node
● Khởi tạo HBox
// Khởi tạo rỗng
HBox hbox = new HBox();

// Khởi tạo với các node


Button button1 = new Button("Button Number 1");
Button button2 = new Button("Button Number 2");
HBox hbox = new HBox(button1, button2);
Layout HBox
public class HBoxExperiments extends Application {

@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("HBox Experiment 1");

Button button1 = new Button("Button Number 1");


Button button2 = new Button("Button Number 2");
Button button3 = new Button("Button Number 3");

HBox hbox = new HBox(button1, button2);


hbox.setSpacing(10);
hbox.setAlignment(Pos.BOTTOM_CENTER);
hbox.getChildren().add(button3);
Scene scene = new Scene(hbox, 400, 100);
primaryStage.setScene(scene);
primaryStage.show();
}

}
Layout HBox

BOTTOM_CENTER

BASELINE_RIGHT

TOP_LEFT
Ví dụ
Viết ứng dụng có giao diện như sau
6
Xử lý sự kiện
(Event handling)
Sự kiện trong JavaFX
Quá trình xử lý sự kiện
Phân loại sự kiện
● Foreground Events: người dùng tương tác trực tiếp với UI controls
○ Click button
○ Nhập văn bản
○ Chọn item trong list
○ Cuộn trang
● Background Events: sự kiện chạy ngầm
○ Báo lỗi
○ Bộ đếm thời gian ngầm
Các sự kiện phổ biến
● Lớp cơ sở: javafx.event.Event
○ Mouse Event (lớp MouseEvent): xử lý sự kiện nhấn chuột (mouse
clicked, mouse pressed, mouse released, mouse moved, …)
○ Key Event (lớp KeyEvent): xử lý sự kiện nhấn phím (key pressed,
key released và key typed)
○ Drag Event (lớp DragEvent): xử lý sự kiện rê chuột (drag entered,
drag dropped, …)
○ Window Event (lớp WindowEvent): xử lý sự kiện hiện/ẩn cửa sổ
Lớp Event
● JavaFX cung cấp các handlers và filters để xử lý sự kiện
● Mỗi sự kiện có 4 thuộc tính:
○ Source: Đối tượng phát sinh sự kiện (chuột, bàn phím, …)
○ Target: Đối tượng nhận sự kiện
○ Type: Kiểu sự kiện (mouse pressed, mouse released, …)
○ Consumed: Sự kiện đã được tiêu thụ (consumed) hay chưa?
● Khi sự kiện xảy ra, event source tạo đối tượng event và chuyển đối tượng
đó tới bộ xử lý sự kiện, nếu sự kiện chưa được consumed thì sẽ xử lý
Ví dụ

Sự kiện nhấp chuột vào nút play:


● Source: chuột
● Target: nút play
● Type: mouse click
Quá trình xử lý sự kiện

1. Target selection

2. Route construction

3. Event capturing

4. Event bubbling
Event Handling - 1. Target selection

● Khi người dùng tương tác (vd: nhấn phím, click chuột vào nút, …)
● Hệ thống xác định phần tử được chọn (vd: nút được clicked)
● Sự kiện được tạo với thông tin:
○ Source: chuột
○ Target: nút
○ Type: click
Event Handling - 2. Route Construction
Tạo chuỗi sự kiện phát sinh (Event Dispatch chain):
đường đi từ stage tới target node
Event Handling - 3. Event Capturing
● Sau khi tạo chuỗi sự kiện, root node sẽ gửi đi sự kiện (dispatch event)
● Trên đường đi, nếu một node nào đó đăng ký filter cho sự kiện sinh ra, filter đó
được thực thi
● Nếu một filter nào đó consume event bằng phương thức consume() từ đối tượng
event tạo ra, kết thúc quá trình xử lý sự kiện
● Nếu event chưa được consumed, sự kiện sẽ truyền tới target node
3. Event Capturing - Event Filter

● Xử lý sự kiện trong giai đoạn Event Capturing

● Một node có thể có một hoặc nhiều filters để xử lý sự kiện

● Có thể dùng một filter cho một hoặc nhiều loại sự kiện

● Có thể consume sự kiện để ngăn quá trình xử lý sự kiện


Ví dụ
Thao tác:
● Người dùng nhập nội dung ở TextField
● Nhấn Button “insert”
● Nội dung hiển thị trong TextArea

Filter:
● Nếu nội dung đã có trong TextArea, không thực hiện insert
Event Handling - 4. Event Bubbling
● Là quá trình lan truyền sự kiện từ target về root
● Sự kiện sẽ đi ngược lên trên: từ target node tới root node
● Nếu một node trong event dispatch chain đăng ký handler cho sự
kiện thì handler sẽ được thực thi
● Ngược lại, sự kiện sẽ chuyển tới root và kết thúc
Event Handling - Một số lưu ý

● Event Handlers và Event Filters: logic để xử lý sự kiện

○ Filter: giai đoạn trước khi sự kiện tới được node mục tiêu

○ Handler: giai đoạn sau khi sự kiện tới được node mục tiêu

● Một node có thể đăng ký nhiều handlers/filters


Event Handling - Thêm/bớt filter
● Thêm filter

//Creating the mouse event handler


EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() {

@Override
public void handle(MouseEvent e) {
System.out.println("Hello World");
circle.setFill(Color.DARKSLATEBLUE);
}

};

//Adding event Filter


Circle.addEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);

● Bỏ filter
circle.removeEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler);
Event Handling - Ví dụ
public class EventFiltersExample extends Application {
@Override
public void start(Stage stage) {
Button button = new Button("Button");
TextArea text = new TextArea();
Circle circle = new Circle(25.0f);
FlowPane fp = new FlowPane(button, text, circle);
fp.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent arg0) {text.appendText("Filter in flow pane\n");}
});

fp.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {


@Override
public void handle(MouseEvent arg0) { text.appendText("Handler in flow pane\n");}
});
Event Handling - Ví dụ

button.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {...});


button.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {...});

circle.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {...});


circle.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {...});
// Creating a scene object
Scene scene = new Scene(fp, 600, 300); stage.setTitle("Event Filters Example");
stage.setScene(scene);
stage.show();
}

public static void main(final String[] args) { Application.launch(EventFiltersExample.class, args);


}
Event Handling - Ví dụ
7
SceneBuilder tool
Công cụ kéo thả giao diện cho JavaFX
Giới thiệu về SceneBuilder
Mục tiêu: tách biệt giữa giao diện và xử lý logic
Các bước thực hiện:
1. Cài đặt SceneBuilder
2. Tạo giao diện (fxml), định nghĩa components và thuộc tính
3. Cài đặt controller
4. Kết nối giao diện fxml với controller
5. Load file xml và chạy
Ví dụ

Nhấn nút “Say Hello”, in dòng chữ Hello World ra textbox


2. Mở file giao diện test.fxml
2. Tạo file test.fxml với SceneBuilder
Chỉnh sửa thuộc tính của button
Chỉnh sửa thuộc tính của button
3. Cài đặt lớp MyController
public class MyController implements Initializable {
@FXML
private Button sayHelloButton;

@FXML
private TextArea textHello;

@Override
public void initialize(URL location, ResourceBundle resources) {
}

public void sayHello(ActionEvent event) {


textHello.setText("Hello World");
}
}

Lưu ý: tên Button và tên TextArea phải khớp với các id tạo trong SceneBuilder
4. Kết nối .fxml với controller
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>

<VBox prefHeight="192.0" prefWidth="371.0"


xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.example.demo_hello.MyController">
<children>
<Button fx:id="sayHelloButton" mnemonicParsing="false" onAction="#sayHello" text="Say Hello" />
<TextArea fx:id="textHello" prefHeight="173.0" prefWidth="162.0"/>
</children>
</VBox>

Lưu ý: thêm thuộc tính fx:controller cho thẻ Vbox, trỏ tới lớp MyController vừa
tạo (dùng full name)
5. Load file fxml trên ứng dụng
public class MyApplication extends Application {

@Override
public void start(Stage stage) throws Exception {
try{
stage.setTitle("My Application");
FXMLLoader loader = new FXMLLoader();
String fxmlActualPath =
"/Users/trinhlk/IdeaProjects/demo_hello/src/main/resources/com/example/demo_hello/test.fxml";
FileInputStream fxmlStream = new FileInputStream(fxmlActualPath);
VBox root = (VBox) loader.load(fxmlStream);
stage.setScene(new Scene(root));
stage.show();
}catch (Exception e){
e.printStackTrace();
}
}

public static void main(String[] args){


launch();
}
}
Thực Hành

You might also like