桌面应用JavaFx
官网
JavaFX 是什么?
JavaFX 是 Java 平台上的下一代 GUI 工具包,最初由 Sun Microsystems 推出,后来归于 Oracle。它的设计理念与 Swing 完全不同,更偏向现代 UI 开发:
•支持 CSS 样式化
•FXML 结构化布局
•内置动画和媒体支持
•更易于绑定与响应式编程
与 Swing 相比,JavaFX 组件更美观、灵活性更强,同时更适合使用 MVVM 模式进行架构设计。
OpenJFX 与 JavaFX 的关系
JavaFX 在 Java 8 中曾是 JDK 的一部分。但从 JDK 11 开始,Oracle 将其剥离出了 JDK,转为一个独立的开源项目:OpenJFX。
| 名称 | 说明 |
|---|---|
| JavaFX | Oracle 的 GUI 工具包 |
| OpenJFX | JavaFX 的开源实现版本 |
目前主流的 JavaFX 开发,基本上都基于 OpenJFX,比如:
•Gluon 提供的 OpenJFX 二进制发布
•Scene Builder 等工具的支持
JavaFX 的核心组成
JavaFX 的体系庞大但清晰,可分为以下模块:
•javafx-base:基本类,如属性绑定
•javafx-controls:UI 控件,如 Button、TableView
•javafx-graphics:场景图、Canvas、绘图等
•javafx-fxml:FXML 解析器
•javafx-media:音视频播放支持
•javafx-web:WebView,嵌入浏览器
此外还有社区维护的扩展库,如:
•ControlsFX:增强 UI 控件
•Flowless:高性能虚拟滚动
•MVVMFX、DataFX:MVVM 框架支持
使用场景
JavaFX 并不是“老掉牙”的选择,它在以下场景中仍然大有可为:
•企业内网应用(无需浏览器)
•数据可视化与监控面板
•工控/医疗设备界面
•教育培训软件
•跨平台桌面客户端
MVVM 架构(推荐)
推荐使用 JDK 17+ 搭配 OpenJFX,同时使用 Maven 或 Gradle 来进行依赖管理。
项目结构
student-http-mvvm/
├── model/
│ └── Student.java
├── service/
│ └── StudentService.java <-- 调用 HTTP 接口
├── view/
│ └── StudentView.fxml
├── viewmodel/
│ └── StudentViewModel.java <-- 绑定属性 + 调用接口
├── controller/
│ └── StudentController.java <-- UI事件 → ViewModel
└── Main.java
mvvm对应类

类解释

调用关系流程
StudentView.fxml (View)
│
└── 绑定 fx:controller → StudentController.java (Controller)
│
└── UI事件转发 → StudentViewModel.java (ViewModel)
│
└── 调用 → StudentService.java (Service)
│
└── 请求/响应 → 后端 HTTP 接口
│
└── JSON 映射 → Student.java (Model)
代码
Maven 依赖(hutool + javafx)
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<!-- JavaFX 控件依赖 -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>17</version>
</dependency>
</dependencies>
model/Student.java
package model;
@Data
public class Student {
private String name;
private int age;
}
service/StudentService.java(使用 Hutool HTTP)
package service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import model.Student;
import java.util.Arrays;
import java.util.List;
public class StudentService {
private final String BASE_URL = "http://localhost:8080";
public List<Student> fetchStudents() {
String resp = HttpRequest.get(BASE_URL + "/students").execute().body();
return JSONUtil.toList(resp, Student.class);
}
public void addStudent(Student student) {
String json = JSONUtil.toJsonStr(student);
HttpRequest.post(BASE_URL + "/students")
.body(json)
.contentType("application/json")
.execute();
}
}
viewmodel/StudentViewModel.java
package viewmodel;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import model.Student;
import service.StudentService;
import java.util.List;
public class StudentViewModel {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty age = new SimpleIntegerProperty();
private final ObservableList<Student> studentList = FXCollections.observableArrayList();
private final StudentService studentService = new StudentService();
public void fetchStudents() {
List<Student> students = studentService.fetchStudents();
studentList.setAll(students);
}
public void saveStudent() {
Student student = new Student(name.get(), age.get());
studentService.addStudent(student);
fetchStudents();
}
public StringProperty nameProperty() { return name; }
public IntegerProperty ageProperty() { return age; }
public ObservableList<Student> getStudentList() { return studentList; }
}
view/StudentView.fxml
<?xml version="1.0" encoding="UTF-8"?>
<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="controller.StudentController">
<center>
<VBox spacing="10" padding="20">
<TextField fx:id="nameField" promptText="姓名"/>
<TextField fx:id="ageField" promptText="年龄"/>
<HBox spacing="10">
<Button text="保存" onAction="#onSave"/>
<Button text="刷新" onAction="#onFetch"/>
</HBox>
<ListView fx:id="studentListView"/>
</VBox>
</center>
</BorderPane>
controller/StudentController.java(UI事件 → ViewModel)
package controller;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.util.converter.NumberStringConverter;
import viewmodel.StudentViewModel;
public class StudentController {
@FXML private TextField nameField;
@FXML private TextField ageField;
@FXML private ListView<String> studentListView;
private final StudentViewModel viewModel = new StudentViewModel();
@FXML
public void initialize() {
nameField.textProperty().bindBidirectional(viewModel.nameProperty());
ageField.textProperty().bindBidirectional(viewModel.ageProperty(), new NumberStringConverter());
// 简单地绑定名称
viewModel.getStudentList().addListener((obs, old, updated) -> {
studentListView.getItems().clear();
viewModel.getStudentList().forEach(s -> {
studentListView.getItems().add(s.getName() + " (" + s.getAge() + ")");
});
});
viewModel.fetchStudents();
}
@FXML
public void onSave() {
viewModel.saveStudent();
}
@FXML
public void onFetch() {
viewModel.fetchStudents();
}
}
启动类 Main.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage stage) throws Exception {
stage.setTitle("学生管理系统");
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/view/StudentView.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 400, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
总结
ViewModel作用
为什么要使用ViewModel,而不是controller直接调用service:
ViewModel 是“逻辑中枢”,Controller 不做业务,Controller 只做桥梁。
如果真的想在某些极简 demo 中简化,也可以跳过 ViewModel,但是只适合玩具项目。在生产系统或教学中,需要坚守 MVVM 架构。
🏆 为什么推荐 MVVM?
• ViewModel 专注做状态和行为管理,职责单一
• Controller 简洁清晰,没有业务逻辑
• FXML 可绑定 ViewModel 的属性:<TextField text="${viewModel.name}" />
• 便于写单元测试,只测试 ViewModel,不依赖 UI
⚠️ 非 MVVM主要问题
• 视图字段(原本ViewModel) name/age/students 都散落在 Controller,状态不集中
• UI 控件和数据逻辑搅在一起,难维护
• 无法绑定:TextField 不支持自动双向绑定
• 无法测试:Controller 依赖 UI 元素,无法单元测试
总结:
非 MVVM 架构一时爽,MVVM 架构保项目后期不爆炸 💥。
开发体验补充推荐
-
Scene Builder:所见即所得
拖拖拽拽构建 FXML,一键绑定 Controller 和 ViewModel,很适合 UI 开发人员和程序员协作。 -
IntelliJ IDEA + MVVMFX 插件
提升开发效率,尤其适合模块化开发与大型应用维护。


浙公网安备 33010602011771号