JavaFX 基础学习(一)
JavaFX 基础学习(一)
内容一:JavaFX 核心三件套
1. Application
javafx.application.Application 是 JavaFX 程序的入口类型。写一个类继承它,JavaFX 会负责:
- 启动 JavaFX 运行环境和 UI 线程
- 创建并管理应用生命周期
- 在合适的时机回调方法,创建窗口和界面
通过 main() 调用 launch(args) 方法,此时 launch() 方法会依次执行 init() start() stop() 方法
init():
- 应用启动前调用一次
- 初始化配置
start():
- 必须实现
- 创建 Scene,摆放 Node,设置 Stage,然后调用 show() 方法
stop():
- 关闭窗口或退出时调用一次
- 保存数据,释放资源
1 | public class Test extends Application{ |
2. Stage
2.1 Title (标题)
1 | stage.setTitle("我的 JavaFX 窗口"); |
2.2 Icon (窗口图标)
常用两种方式:
方式 1:从 classpath 资源加载
1 | stage.getIcons().add(new Image( |
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
2Stage stage = new Stage();
stage.initStyle(StageStyle.DECORATED);
2.5 Modality (模态)
Modality.NONE:默认,不阻塞Modality.WINDOW_MODAL:阻塞“父窗口”(owner)Modality.APPLICATION_MODAL:阻塞整个应用所有窗口
2.6 event (事件)
常用的是“窗口关闭”相关事件:
1 | stage.setOnCloseRequest(event -> { |
3. Scene + Node
3.1 Scene 是什么
Scene = 窗口里的一整套“内容容器”。Stage 负责显示,Scene 负责“装内容”。
核心点:
- 一个
Stage同一时刻只能显示一个Scene Scene里必须有一个 root(根节点),它是一棵 Node 树的根
常用写法:
1 | Scene scene = new Scene(root, 800, 600); |
3.2 Node 是什么
Node = 所有能放进界面的东西的统称
Node 主要分两类:
控件 Controls:
Button、Label、TextField等布局容器 Panes:
VBox、HBox、BorderPane、GridPane等容器本身也是 Node,并且可以包含子 Node
3.3 Scene Graph(节点树)
JavaFX 的界面结构是一棵树(Scene Graph):
- root(通常是某个 Pane,例如 VBox)
- 子节点:Label(“只显示文字”的控件)
- 子节点:Button
- 子节点:HBox
- TextField
- Button
示例:
1 | Label title = new Label("Login"); // 创建了一个标签,显示 Login |
3.4 Scene 常用属性与用法
(1) 尺寸
- 在
new Scene(root, w, h)里给初始大小 - 或通过
stage.setWidth/Height控制窗口
(2) 样式表 CSS
1 | scene.getStylesheets().add( |
(3) 设置背景填充(比如透明窗)
1 | scene.setFill(Color.TRANSPARENT); |
(4) 查找节点
给节点设置 id:
1 | button.setId("submitBtn"); |
再查找:
1 | Node n = scene.lookup("#submitBtn"); |
3.5 Node 常用属性
- 位置尺寸相关:
setPrefWidth/Height、setMin...、setMax... - 可见与可用:
1 | node.setVisible(true); |
- 样式类:
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 | VBox root = new VBox(10); // 10 = 间距 spacing |
常用属性:
new VBox(spacing)root.setAlignment(Pos.CENTER_LEFT)(控制整体对齐)VBox.setVgrow(node, Priority.ALWAYS)(让某个子节点“尽量长高”)
2. HBox(横排)
从左到右排,适合做一行两个控件(比如输入框 + 按钮)。
1 | TextField tf = new TextField(); |
让输入框占满剩余空间:
1 | HBox.setHgrow(tf, Priority.ALWAYS); |
3. BorderPane(经典五区)
上、下、左、右、中 五个区域。做主界面骨架
1 | BorderPane root = new BorderPane(); |
特点:
center会自动吃掉剩余空间- 常用来做:顶部工具栏 + 左侧菜单 + 中间内容区
内容三:控件 Controls
1. Label(标签控件)
Label 用来显示一段文本或图标。它本身不负责输入,通常用于标题、说明文字、结果展示。
1.1 创建与显示
1 | Label label = new Label("Hello"); |
把它放进布局容器(比如 VBox)里,才能在窗口里看到:
1 | VBox root = new VBox(label); |
1.2 常用的 6 个方法
a. 设置/获取文本
1 | label.setText("Login"); |
b. 自动换行
1 | label.setWrapText(true); |
c. 字体(大小、粗细)
1 | label.setFont(Font.font("System", FontWeight.BOLD, 18)); //label.setFont( Font.font( 字体族, 字重, 字号 ) ); |
d. 对齐
1 | label.setAlignment(Pos.CENTER_LEFT); |
e. 文本颜色
1 | label.setTextFill(Color.DODGERBLUE); |
f. Tooltip(鼠标悬停提示)
1 | label.setTooltip(new Tooltip("提示信息")); |
2. Button(按钮控件)
Button 用来触发动作。
核心:
- 创建和设置文字
- 绑定点击事件(setOnAction)
2.1 创建与基本用法
1 | Button button = new Button("提交"); |
常用尺寸设置
1 | button.setPrefWidth(120); // 宽度 |
2.2 点击事件 setOnAction
1 | button.setOnAction(e -> { |
过程:
- 用户点击按钮
- 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 | TextField tf = new TextField(); |
3.2 读取、设置、清空输入内容
1 | String text = tf.getText(); // 读取 |
3.3 点击读取输入
常见用法:点击按钮,把输入框内容显示到 Label。
1 | Label out = new Label("等待输入…"); |
3.4监听输入变化(输入时就响应)
用户一边输入,一边更新提示/校验:
1 | tf.textProperty().addListener((obs, oldText, newText) -> { |
4. TextArea(多行输入框)
TextArea 用来输入多行文本,比如备注、日志、文章内容。
4.1 创建与占位提示
1 | TextArea ta = new TextArea(); |
也可以给默认内容:
1 | TextArea ta = new TextArea("第一行\n第二行"); |
4.2 读取、设置、清空内容
1 | String text = ta.getText(); // 读取全部文本 |
4.3 常用显示
a. 自动换行
1 | ta.setWrapText(true); |
b. 设定行数/高度
1 | ta.setPrefRowCount(6); |
c. 只读(展示日志时常用)
1 | ta.setEditable(false); |
4.4 监听内容变化(输入时实时响应)
1 | ta.textProperty().addListener((obs, oldV, newV) -> { |
5.CheckBox(复选框)
CheckBox 表示一个可勾选/取消的选项,典型用途是“记住我”“同意协议”“开启某功能”。
5.1 创建与默认状态
1 | CheckBox cb = new CheckBox("记住我"); |
读取是否勾选:
1 | boolean checked = cb.isSelected(); |
5.2 监听勾选变化
方式 1:直接用 setOnAction
1 | cb.setOnAction(e -> { |
方式 2:监听属性 selectedProperty()
1 | cb.selectedProperty().addListener((obs, oldV, newV) -> { |
5.3 常见的同意协议
1 | Label out = new Label("请先勾选同意协议"); |
6. RadioButton(单选按钮)
RadioButton 表示多个选项里只能选一个。要实现单选,必须把多个 RadioButton 放进同一个 ToggleGroup
示例:
1 | Label out = new Label("请选择一个选项"); |
7.ComboBox(下拉选择框)
ComboBox<> 用来从一组候选项里选一个。它和 RadioButton + ToggleGroup 类似,都是单选,只是展示形式变成下拉框。
7.1 创建加添加选项
1 | ComboBox<String> cb = new ComboBox<>(); |
7.2 读取当前选中值
1 | String value = cb.getValue(); |
7.3 监听选择变化
1 | cb.valueProperty().addListener((obs, oldV, newV) -> { |
7.4 常用设置
a. 可输入
1 | cb.setEditable(true); |
b. 设置提示文字
1 | cb.setPromptText("提示文字"); |
c. 禁用
1 | cb.setDisable(true); |
8. ListView(列表)
ListView<> 用来显示一组数据的可滚动列表,用户可以点击选择其中一项(也可以配置多选)。
8.1 创建并填充数据
1 | ListView<String> list = new ListView<>(); |
8.2 获取用户选择的项
1 | Label out = new Label("请选择一项"); |
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 | list.getItems().add("New Item"); |
9.Slider(滑块)+ ProgressBar(进度条)
Slider 提供一个 0~1 或 0~100 的值,ProgressBar 显示进度
9.1 Slider 用法
1 | Slider slider = new Slider(0, 100, 30); // 最小值, 最大值, 初始值 |
9.2 ProgressBar 用法
ProgressBar 的进度值是一个 double,范围通常是:
0.0到1.0:表示 0% 到 100%-1:表示不确定进度(一直滚动)
1 | ProgressBar bar = new ProgressBar(0); // 0% |
不确定进度(例如“正在加载中”):
1 | bar.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS); // 等价于 -1 |
内容四:事件与属性绑定
1. 事件
事件就是“用户做了某个操作 → 触发回调函数”。常见事件源有 Button、TextField、任意 Node(鼠标/键盘)。
1.1 Action 事件
Button 点击、TextField 按回车 都属于 Action 事件:
1 | ok.setOnAction(e -> { |
1.2 鼠标/键盘事件
任何 Node 都可以监听:
1 | node.setOnMouseClicked(e -> System.out.println("clicked")); |
2. 属性
JavaFX 里大量东西不是普通字段,而是可观察的属性
- 你可以监听变化(监听器)
- 你可以绑定(binding):让一个值自动跟随另一个值变化
3. 监听
1 | name.textProperty().addListener((obs, oldV, 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