JavaFX 详细指南
1. JavaFX 简介
JavaFX 是一个用于构建富客户端应用程序的 Java 库,它提供了一个轻量级的、硬件加速的 Java UI 平台。作为 Java 标准库的一部分(JDK 8 到 JDK 10),JavaFX 旨在替代 Swing 成为 Java 应用程序开发的主要 GUI 库。
1.1 历史与发展
- 2008年:JavaFX 1.0 发布,最初使用一种名为 JavaFX Script 的脚本语言
- 2011年:JavaFX 2.0 发布,脚本语言被完全替换为 Java API
- 2014年:JavaFX 8 随 Java 8 一起发布,正式集成到 Java SE
- 2018年:Oracle 宣布从 JDK 11 开始,JavaFX 将作为独立模块发布,不再包含在 JDK 中
- 现在:JavaFX 由 OpenJFX 社区维护和开发,作为开源项目继续发展
1.2 主要特性
- 现代化 UI:支持 CSS 样式、动画和视觉特效
- FXML:基于 XML 的声明式 UI 定义语言
- Scene Builder:可视化布局设计工具
- WebView:集成 Web 内容的组件
- 多媒体支持:音频、视频和图像处理
- 3D 图形支持:三维场景渲染能力
- 跨平台:在 Windows、macOS、Linux 等平台上一致运行
2. JavaFX 架构
JavaFX 采用了一种模块化的架构,由以下几个主要部分组成:
2.1 基本架构组件
- Stage:顶层容器,相当于应用程序的窗口
- Scene:包含 UI 元素的容器,Stage 中可以切换不同的 Scene
- Scene Graph:场景图,一个树状结构,包含了所有 UI 元素
- Nodes:场景图中的节点,可以是控件、容器、形状等
2.2 生命周期
一个 JavaFX 应用程序通常继承自 javafx.application.Application
类,其生命周期包括:
public class HelloWorld extends Application {
@Override
public void init() throws Exception {
// 初始化应用程序
// 注意:此方法不在 JavaFX 应用程序线程上调用
}
@Override
public void start(Stage primaryStage) throws Exception {
// 启动应用程序,设置和显示 UI
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(new StackPane(new Label("Hello World")), 300, 200));
primaryStage.show();
}
@Override
public void stop() throws Exception {
// 应用程序关闭时调用,进行资源清理
}
public static void main(String[] args) {
launch(args); // 启动 JavaFX 应用
}
}
3. Scene Graph 与布局
3.1 Scene Graph(场景图)
场景图是 JavaFX 应用中所有视觉元素的容器,它是一个树状结构:
- 根节点:每个场景图都有一个根节点
- 分支节点:可以包含其他节点的节点(如 Pane、Group)
- 叶节点:不能包含其他节点的节点(如 Button、Label)
3.2 常用布局容器
JavaFX 提供了多种布局容器,用于组织控件的排列:
3.2.1 BorderPane
将空间分为五个区域:top、right、bottom、left 和 center。
BorderPane borderPane = new BorderPane();
borderPane.setTop(new Label("Top"));
borderPane.setRight(new Label("Right"));
borderPane.setBottom(new Label("Bottom"));
borderPane.setLeft(new Label("Left"));
borderPane.setCenter(new Label("Center"));
3.2.2 HBox 和 VBox
HBox 将子节点水平排列,VBox 将子节点垂直排列:
HBox hbox = new HBox(10); // 10px 间距
hbox.getChildren().addAll(new Button("Button 1"), new Button("Button 2"));
VBox vbox = new VBox(10); // 10px 间距
vbox.getChildren().addAll(new Label("Label 1"), new Label("Label 2"));
3.2.3 GridPane
将空间分割成灵活的网格:
GridPane grid = new GridPane();
grid.setHgap(10); // 水平间距
grid.setVgap(10); // 垂直间距
grid.add(new Label("用户名:"), 0, 0);
grid.add(new TextField(), 1, 0);
grid.add(new Label("密码:"), 0, 1);
grid.add(new PasswordField(), 1, 1);
3.2.4 StackPane
将所有子节点堆叠在一起:
StackPane stack = new StackPane();
Rectangle rect = new Rectangle(100, 100, Color.BLUE);
Label label = new Label("Stacked");
stack.getChildren().addAll(rect, label);
3.2.5 FlowPane
类似于 HTML 中的流式布局:
FlowPane flow = new FlowPane();
flow.setPadding(new Insets(10));
flow.setHgap(10);
flow.setVgap(10);
for (int i = 0; i < 10; i++) {
flow.getChildren().add(new Button("Button " + i));
}
3.3 布局约束与大小控制
JavaFX 提供了多种方式来控制节点的大小和位置:
- Preferred/Min/Max Size:设置节点的首选/最小/最大尺寸
- Margins:设置节点周围的空间
- Alignment:在父容器中的对齐方式
- AnchorPane Constraints:从容器边缘的固定距离
Button button = new Button("Button");
button.setPrefSize(100, 40);
button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
HBox.setMargin(button, new Insets(10));
HBox.setHgrow(button, Priority.ALWAYS);
4. UI 控件
JavaFX 提供了丰富的 UI 控件库,用于构建交互式应用。
4.1 基本控件
4.1.1 Label 和 Text
用于显示文本:
Label label = new Label("这是一个标签");
Text text = new Text("这是一个文本节点");
text.setFont(Font.font("Arial", FontWeight.BOLD, 14));
4.1.2 按钮类控件
Button button = new Button("点击我");
button.setOnAction(e -> System.out.println("按钮被点击"));
CheckBox checkBox = new CheckBox("选择我");
checkBox.setSelected(true);
RadioButton radioButton = new RadioButton("单选");
ToggleGroup group = new ToggleGroup();
radioButton.setToggleGroup(group);
4.1.3 文本输入控件
TextField textField = new TextField("可编辑文本");
PasswordField passwordField = new PasswordField();
TextArea textArea = new TextArea("多行文本");
4.2 高级控件
4.2.1 TableView
用于显示表格数据:
TableView<Person> table = new TableView<>();
TableColumn<Person, String> nameCol = new TableColumn<>("姓名");
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
TableColumn<Person, Integer> ageCol = new TableColumn<>("年龄");
ageCol.setCellValueFactory(new PropertyValueFactory<>("age"));
table.getColumns().addAll(nameCol, ageCol);
table.getItems().add(new Person("张三", 30));
4.2.2 ListView 和 TreeView
列表和树形结构显示:
ListView<String> listView = new ListView<>();
listView.getItems().addAll("项目 1", "项目 2", "项目