JavaFX 基础学习(一)

JavaFX 基础学习(一)

Lovien Lv1

JavaFX 基础学习(一)

内容一:JavaFX 核心三件套

1. Application

javafx.application.ApplicationJavaFX 程序的入口类型。写一个类继承它,JavaFX 会负责:

  • 启动 JavaFX 运行环境和 UI 线程
  • 创建并管理应用生命周期
  • 在合适的时机回调方法,创建窗口和界面

通过 main() 调用 launch(args) 方法,此时 launch() 方法会依次执行 init() start() stop() 方法

  • init():

    • 应用启动前调用一次
    • 初始化配置
  • start():

    • 必须实现
    • 创建 Scene,摆放 Node,设置 Stage,然后调用 show() 方法
  • stop():

    • 关闭窗口或退出时调用一次
    • 保存数据,释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test extends Application{

public static void main(String[] args){
Application.launch(args);
}

@Override
public void start(Stage stage){

}

}


2. Stage

2.1 Title (标题)

1
stage.setTitle("我的 JavaFX 窗口");

2.2 Icon (窗口图标)

常用两种方式:

方式 1:从 classpath 资源加载

1
2
3
stage.getIcons().add(new Image(
getClass().getResourceAsStream("/icons/app.png")
));
  • app.png 放在 resources/icons/app.png

**方式 2:用 URL / 文件路径 **

1
stage.getIcons().add(new Image("file:/D:/icons/app.png"));

2.3 Resiziable (是否允许改变窗口大小)

1
stage.setResizable(false); // 默认 true

2.4 StageStyle (窗口样式)

  • StageStyle 会影响标题栏、边框等外观。常见的有:

    • StageStyle.DECORATED:默认,有标题栏和边框
    • StageStyle.UNDECORATED:无标题栏(自己做拖拽、关闭按钮)
    • StageStyle.TRANSPARENT:透明窗口(常用于自定义浮层)
    • StageStyle.UTILITY:工具窗口风格(轻量的标题栏)

    用法(注意:必须在 show() 之前调用):

    1
    2
    Stage stage = new Stage();
    stage.initStyle(StageStyle.DECORATED);

2.5 Modality (模态)

  • Modality.NONE:默认,不阻塞
  • Modality.WINDOW_MODAL:阻塞“父窗口”(owner)
  • Modality.APPLICATION_MODAL:阻塞整个应用所有窗口

2.6 event (事件)

常用的是“窗口关闭”相关事件:

1
2
3
4
5
6
stage.setOnCloseRequest(event -> {
event.consume();

//

});

3. Scene + Node

3.1 Scene 是什么

Scene = 窗口里的一整套“内容容器”Stage 负责显示,Scene 负责“装内容”。

核心点:

  • 一个 Stage 同一时刻只能显示一个 Scene
  • Scene 里必须有一个 root(根节点),它是一棵 Node 树的根

常用写法:

1
2
3
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();

3.2 Node 是什么

Node = 所有能放进界面的东西的统称

Node 主要分两类:

  • 控件 ControlsButtonLabelTextField

  • 布局容器 PanesVBoxHBoxBorderPaneGridPane

    容器本身也是 Node,并且可以包含子 Node


3.3 Scene Graph(节点树)

JavaFX 的界面结构是一棵树(Scene Graph):

  • root(通常是某个 Pane,例如 VBox)
    • 子节点:Label(“只显示文字”的控件)
    • 子节点:Button
    • 子节点:HBox
      • TextField
      • Button

示例:

1
2
3
4
5
6
7
8
9
10
11
12
Label title = new Label("Login"); // 创建了一个标签,显示 Login
TextField username = new TextField(); // 创建一个输入框,并设置提示文字,TextField 是单行输入框。
username.setPromptText("Username");

Button submit = new Button("Submit"); // 创建一个按钮

VBox root = new VBox(10, title, username, submit); // VBox 是 root
root.setPadding(new Insets(20)); // 给 VBox 加内边距 Insets(20) 表示上下左右都留 20 像素的边距

Scene scene = new Scene(root, 400, 250);
stage.setScene(scene);
stage.show();

3.4 Scene 常用属性与用法

(1) 尺寸

  • new Scene(root, w, h) 里给初始大小
  • 或通过 stage.setWidth/Height 控制窗口

(2) 样式表 CSS

1
2
3
scene.getStylesheets().add(
getClass().getResource("/css/app.css").toExternalForm()
);

(3) 设置背景填充(比如透明窗)

1
scene.setFill(Color.TRANSPARENT);

(4) 查找节点

给节点设置 id:

1
button.setId("submitBtn");

再查找:

1
Node n = scene.lookup("#submitBtn");

3.5 Node 常用属性

  • 位置尺寸相关:setPrefWidth/HeightsetMin...setMax...
  • 可见与可用:
1
2
node.setVisible(true);
node.setDisable(false);
  • 样式类:
1
node.getStyleClass().add("primary-button");
  • 事件(任何 Node 基本都能绑鼠标键盘事件):
1
node.setOnMouseClicked(e -> System.out.println("clicked"));

3.6 Scene 切换

最简单的“换页面”就是换 root 或换 Scene:

方式 1:换 Scene

1
stage.setScene(scene2);

方式 2:同一个 Scene,换 root

1
scene.setRoot(newRoot);

内容二:布局 Layout

在 JavaFX 里,布局(Layout)就是用“容器 Pane”来决定子控件怎么摆放

常见规律是:

  • Pane
  • 把控件(子 Node)放进容器
  • 容器按自己的规则(横排、竖排、网格、边框等)排版

1. VBox(竖排)

从上到下排,最适合做“表单页面”。

1
2
3
VBox root = new VBox(10);     // 10 = 间距 spacing
root.setPadding(new Insets(20));
root.getChildren().addAll(new Label("Login"), new TextField(), new Button("Submit"));

常用属性:

  • new VBox(spacing)
  • root.setAlignment(Pos.CENTER_LEFT)(控制整体对齐)
  • VBox.setVgrow(node, Priority.ALWAYS)(让某个子节点“尽量长高”)

2. HBox(横排)

从左到右排,适合做一行两个控件(比如输入框 + 按钮)。

1
2
3
4
5
TextField tf = new TextField();
Button btn = new Button("Search");

HBox row = new HBox(10, tf, btn);
row.setAlignment(Pos.CENTER_LEFT);

让输入框占满剩余空间:

1
2
HBox.setHgrow(tf, Priority.ALWAYS);
tf.setMaxWidth(Double.MAX_VALUE);

3. BorderPane(经典五区)

上、下、左、右、中 五个区域。做主界面骨架

1
2
3
4
BorderPane root = new BorderPane();
root.setTop(new Label("Top Bar"));
root.setLeft(new Label("Menu"));
root.setCenter(new Label("Main Content"));

特点:

  • center 会自动吃掉剩余空间
  • 常用来做:顶部工具栏 + 左侧菜单 + 中间内容区

内容三:控件 Controls

1. Label(标签控件)

Label 用来显示一段文本或图标。它本身不负责输入,通常用于标题、说明文字、结果展示。

1.1 创建与显示

1
Label label = new Label("Hello");

把它放进布局容器(比如 VBox)里,才能在窗口里看到:

1
2
3
4
VBox root = new VBox(label);
Scene scene = new Scene(root, 300, 200);
stage.setScene(scene);
stage.show();

1.2 常用的 6 个方法

a. 设置/获取文本
1
2
label.setText("Login");
String t = label.getText();
b. 自动换行
1
label.setWrapText(true);
c. 字体(大小、粗细)
1
label.setFont(Font.font("System", FontWeight.BOLD, 18)); //label.setFont( Font.font( 字体族, 字重, 字号 ) );
d. 对齐
1
2
label.setAlignment(Pos.CENTER_LEFT);
label.setMaxWidth(Double.MAX_VALUE); // 想让对齐生效,通常要给它可用宽度
e. 文本颜色
1
label.setTextFill(Color.DODGERBLUE);
f. Tooltip(鼠标悬停提示)
1
label.setTooltip(new Tooltip("提示信息"));

2. Button(按钮控件)

Button 用来触发动作。

核心:

  • 创建和设置文字
  • 绑定点击事件(setOnAction)

2.1 创建与基本用法

1
2
3
Button button = new Button("提交");
button.setText("确定"); // 修改按钮文字
button.setDisable(false); // 禁用/启用按钮(true=灰掉不可点)

常用尺寸设置

1
2
button.setPrefWidth(120);   // 宽度
button.setPrefHeight(36); // 高度

2.2 点击事件 setOnAction

1
2
3
button.setOnAction(e -> {
System.out.println("按钮被点击了");
});

过程:

  • 用户点击按钮
  • JavaFX 触发一个 ActionEvent
  • 运行写的这段代码

2.3 常见用法

a. 默认按钮(回车触发)

在表单里很常见:

1
button.setDefaultButton(true);
b. 取消按钮(ESC 触发)
1
button.setCancelButton(true);
c. 给按钮加样式
1
button.getStyleClass().add("primary-button");

3. TextField(单行输入框)

TextField 用来让用户输入一行文字

核心:

  • 创建、提示文字
  • 读写内容
  • 监听变化

3.1 创建与提示文字

1
2
TextField tf = new TextField();
tf.setPromptText("请输入用户名"); // 灰色占位提示

3.2 读取、设置、清空输入内容

1
2
3
String text = tf.getText();  // 读取
tf.setText("hello"); // 设置
tf.clear(); // 清空

3.3 点击读取输入

常见用法:点击按钮,把输入框内容显示到 Label。

1
2
3
4
5
6
7
8
9
10
11
Label out = new Label("等待输入…");
TextField name = new TextField();
name.setPromptText("Name");

Button ok = new Button("确定");
ok.setOnAction(e -> out.setText("Hello, " + name.getText()));

VBox root = new VBox(10, out, name, ok);
root.setPadding(new Insets(20));
stage.setScene(new Scene(root, 360, 180));
stage.show();

3.4监听输入变化(输入时就响应)

用户一边输入,一边更新提示/校验:

1
2
3
tf.textProperty().addListener((obs, oldText, newText) -> {
System.out.println("新内容: " + newText);
});

4. TextArea(多行输入框)

TextArea 用来输入多行文本,比如备注、日志、文章内容。

4.1 创建与占位提示

1
2
TextArea ta = new TextArea();
ta.setPromptText("请输入多行内容…");

也可以给默认内容:

1
TextArea ta = new TextArea("第一行\n第二行");

4.2 读取、设置、清空内容

1
2
3
String text = ta.getText(); // 读取全部文本
ta.setText("new text"); // 设置全部文本
ta.clear(); // 清空

4.3 常用显示

a. 自动换行
1
ta.setWrapText(true);
b. 设定行数/高度
1
2
ta.setPrefRowCount(6);      
ta.setPrefColumnCount(20);
c. 只读(展示日志时常用)
1
ta.setEditable(false);

4.4 监听内容变化(输入时实时响应)

1
2
3
ta.textProperty().addListener((obs, oldV, newV) -> {
System.out.println("长度: " + newV.length());
});

5.CheckBox(复选框)

CheckBox 表示一个可勾选/取消的选项,典型用途是“记住我”“同意协议”“开启某功能”。

5.1 创建与默认状态

1
2
CheckBox cb = new CheckBox("记住我");
cb.setSelected(true); // 默认勾选

读取是否勾选:

1
boolean checked = cb.isSelected();

5.2 监听勾选变化

方式 1:直接用 setOnAction

1
2
3
cb.setOnAction(e -> {
System.out.println("是否勾选: " + cb.isSelected());
});

方式 2:监听属性 selectedProperty()

1
2
3
cb.selectedProperty().addListener((obs, oldV, newV) -> {
System.out.println("从 " + oldV + " 变为 " + newV);
});

5.3 常见的同意协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Label out = new Label("请先勾选同意协议");
CheckBox agree = new CheckBox("我已阅读并同意协议");
Button next = new Button("下一步");
next.setDisable(true); // 默认不可点

agree.selectedProperty().addListener((obs, oldV, newV) -> {
next.setDisable(!newV); // 勾选后才启用
out.setText(newV ? "可以继续了" : "请先勾选同意协议");
});

VBox root = new VBox(10, out, agree, next);
root.setPadding(new Insets(20));
stage.setScene(new Scene(root, 420, 200));
stage.show();

6. RadioButton(单选按钮)

RadioButton 表示多个选项里只能选一个。要实现单选,必须把多个 RadioButton 放进同一个 ToggleGroup

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Label out = new Label("请选择一个选项");

RadioButton r1 = new RadioButton("1");
RadioButton r2 = new RadioButton("2");
RadioButton r3 = new RadioButton("3");

ToggleGroup group = new ToggleGroup(); // 创建单选组
r1.setToggleGroup(group); // 把每个 RadioButton 绑定到同一个组里。同组才会互斥。
r2.setToggleGroup(group);
r3.setToggleGroup(group);

r1.setSelected(true); // 默认选中一个

group.selectedToggleProperty().addListener((obs, oldV, newV) -> { // 监听“当前选中的按钮”变化
if (newV != null) {
RadioButton selected = (RadioButton) newV;
out.setText("你选择了: " + selected.getText());
}
});

VBox root = new VBox(10, out, r1, r2, r3);
root.setPadding(new Insets(20));
stage.setScene(new Scene(root, 420, 240));
stage.show();

7.ComboBox(下拉选择框)

ComboBox<> 用来从一组候选项里选一个。它和 RadioButton + ToggleGroup 类似,都是单选,只是展示形式变成下拉框

7.1 创建加添加选项

1
2
ComboBox<String> cb = new ComboBox<>();
cb.getItems().addAll("1", "2", "3");

7.2 读取当前选中值

1
String value = cb.getValue(); 

7.3 监听选择变化

1
2
3
cb.valueProperty().addListener((obs, oldV, newV) -> {
out.setText("你选择了: " + newV);
});

7.4 常用设置

a. 可输入
1
cb.setEditable(true);
b. 设置提示文字
1
cb.setPromptText("提示文字");
c. 禁用
1
cb.setDisable(true);

8. ListView(列表)

ListView<> 用来显示一组数据的可滚动列表,用户可以点击选择其中一项(也可以配置多选)。

8.1 创建并填充数据

1
2
ListView<String> list = new ListView<>();
list.getItems().addAll("1", "2", "3");

8.2 获取用户选择的项

1
2
3
4
5
Label out = new Label("请选择一项");

list.getSelectionModel().selectedItemProperty().addListener((obs, oldV, newV) -> {
out.setText("你选择了: " + newV);
});

8.3 设置默认选中

1
list.getSelectionModel().select(0); // 选中第 1 项

8.4 单选、多选模式

默认是单选。想多选:

1
list.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

读取所有选中项(多选时):

1
ObservableList<String> selected = list.getSelectionModel().getSelectedItems();

8.5 常见增删改列表数据

1
2
3
4
list.getItems().add("New Item");
list.getItems().remove("Web");
list.getItems().set(0, "JavaFX (Updated)");
list.getItems().clear();

9.Slider(滑块)+ ProgressBar(进度条)

Slider 提供一个 0~1 或 0~100 的值,ProgressBar 显示进度

9.1 Slider 用法

1
2
3
4
5
6
7
8
9
10
11
12
Slider slider = new Slider(0, 100, 30); // 最小值, 最大值, 初始值
slider.setShowTickMarks(true); // 显示刻度线
slider.setShowTickLabels(true); // 显示刻度文字
slider.setMajorTickUnit(10); // 主刻度间隔
slider.setMinorTickCount(4); // 主刻度之间的次刻度数量
slider.setBlockIncrement(1); // 键盘/点击时的步进

double v = slider.getValue(); // 读取值

slider.valueProperty().addListener((obs, oldV, newV) -> { // 监听值变化
System.out.println("当前值: " + newV.doubleValue());
});

9.2 ProgressBar 用法

ProgressBar 的进度值是一个 double,范围通常是:

  • 0.01.0:表示 0% 到 100%
  • -1:表示不确定进度(一直滚动)
1
2
ProgressBar bar = new ProgressBar(0); // 0%
bar.setProgress(0.6); // 60%

不确定进度(例如“正在加载中”):

1
bar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS); // 等价于 -1

内容四:事件与属性绑定

1. 事件

事件就是“用户做了某个操作 → 触发回调函数”。常见事件源有 Button、TextField、任意 Node(鼠标/键盘)。

1.1 Action 事件

Button 点击TextField 按回车 都属于 Action 事件:

1
2
3
ok.setOnAction(e -> {
System.out.println("触发了 ActionEvent");
});

1.2 鼠标/键盘事件

任何 Node 都可以监听:

1
2
node.setOnMouseClicked(e -> System.out.println("clicked"));
scene.setOnKeyPressed(e -> System.out.println(e.getCode()));

2. 属性

JavaFX 里大量东西不是普通字段,而是可观察的属性

  • 你可以监听变化(监听器)
  • 你可以绑定(binding):让一个值自动跟随另一个值变化

3. 监听

1
2
3
name.textProperty().addListener((obs, oldV, newV) -> {
out.setText("当前输入: " + newV);
});

含义:

  • obs:被监听的属性对象(通常不用)
  • oldV:旧值
  • newV:新值

4.绑定

4.1 单向绑定:A 由 B 决定

Label 永远显示 TextField 的内容:

1
out.textProperty().bind(name.textProperty());

执行之后:

  • 不需要写监听器也能联动
  • 不能 out.setText(...)(会报错:因为它被 bind 了)

更常见的是加工后再绑定(字符串拼接):

1
out.textProperty().bind(name.textProperty().concat(" <- 这是输入框内容"));

4.2 绑定按钮禁用状态

输入为空时禁用按钮:

1
ok.disableProperty().bind(name.textProperty().isEmpty());

逻辑:

  • name 为空 → isEmpty 为 true → ok 执行 disable
  • name 不为空 → ok 启用

5. 双向绑定

两个属性互相同步,比如两个输入框内容保持一致:

1
tf1.textProperty().bindBidirectional(tf2.textProperty());

特点:

  • 改 tf1 会更新 tf2
  • 改 tf2 也会更新 tf1
目录
JavaFX 基础学习(一)