摘要:本教程介绍了Java最新图形化界面开发技术——JavaFx,包括UI控件用法介绍、属性绑定、事件监听和FXML。通过学习本教程,读者可以掌握JavaFx的基本概念和核心技术,学会使用各种UI控件,掌握属性绑定和事件监听机制,以及使用FXML构建Java应用程序界面的方法。本教程为开发者提供了全面的JavaFx开发指南,帮助读者快速入门并提升Java图形界面开发技能。
文章目录
- 一、JavaFx介绍
- 1、JavaFx简介
- 2、可用性
- 3、主要特征
- 4、UI控件
- 二、JavaFx概述
- 1、JavaFx结构图
- 2、JavaFx组件
- (1)舞台
- (2)场景
- ① 场景图
- ② 节点
- (3)控件
- (4)布局
- (5)图表
- (6)2D图形
- (7)3D图形
- (8)声音
- (9)视频
- 三、JavaFx快速入门
- 1、IDEA配置JavaFx环境
- 2、编码与运行
- 四、组件功能介绍
- 1、Application
- 2、Stage舞台(窗口)
- (1)创建舞台
- (2)展示舞台
- (3)在舞台上设置场景
- (4)舞台标题
- (5)舞台位置
- (6)舞台宽度和高度
- (7)舞台风格
- (8)舞台全屏模式
- (9)阶段生命周期事件
- (10)键盘或鼠标事件
- 3、Scene场景
- (1)创建场景
- (2)在舞台上设置场景
- (3)场景鼠标光标
- 4、Node节点 UI控件的通用属性
- (1)控件节点坐标系
- (2)设置控件坐标
- (3)设置控件风格
- (4)设置控件首要背景宽度和高度
- (5)设置文本居中
- (6)设置是否显示/隐藏该控件
- (7)设置控件半透明值
- (8)设置控件旋转角度
- (9)设置控件X轴和Y轴平移量
- 5、UI控件的属性绑定和属性监听
- 6、JavaFx应用里的事件驱动编程
- 7、Color、Font、Image
- (1)Color颜色
- (2)Font字体
- (3)Image图片
- 五、FXML
- 1、FXML布局文件的使用
- 2、Scene Builder里构建fxml布局文件
- 3、Controller里的initialize方法
- 4、在Application里操作Controller
- 六、JavaFx多线程操作Platform.runLater
JavaFx是Java图形化界面技术AWT、Swing技术的新替代品,如果想系统学习JavaFx,推荐一个B站UP主:https://space.bilibili.com/5096022/channel/collectiondetail?sid=210809
如果是想快速入门JavaFx,推荐视频:
https://www.bilibili.com/video/BV1H14y1g7ji/
https://www.bilibili.com/video/BV1Qf4y1F7Zv/
如果你因毕设或项目中用到图形化界面技术JavaFx,赶时间都不想看,请看下面的文字版,通过多个案例,直接带你快速入门JavaFx,轻松上手看懂并学会使用!一、JavaFx介绍
1、JavaFx简介
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。
JavaFX允许开发人员快速构建丰富的跨平台应用程序。JavaFX通过硬件加速图形支持现代GPU。
JavaFX允许开发人员在单个编程接口中组合图形,动画和UI控件。
图表编程语言可用于开发互联网应用程序(RIA)。JavaFX技术主要应用于创建Rich internet applications(RIAs)。当前的JavaFX包括JavaFX脚本和JavaFX Mobile (一种运营于行动装置的操作系统),今后JavaFX将包括更多的产品。JavaFX Script编程语言 (以下称为JavaFX) 是一种声明性的、静态类型脚本语言。
JavaFX技术有着良好的前景,包括可以直接调用Java API的能力。因为JavaFX Script是静态类型,它同样具有结构化代码、重用性和封装性,如包、类、继承和单独编译和发布单元,这些特性使得使用JavaFX技术创建和管理大型程序变为可能。JavaFx官网:https://openjfx.io/
下面是基于JavaFx实现的一些第三方开发案例和应用场景:2、可用性
JavaFX API与Java SE运行时环境(JRE)和Java开发工具包(JDK)绑在一起。
JDK可用于所有主要的桌面平台,Windows,Mac OS X和Linux。JavaFX应用程序可以在所有主要的桌面平台上编译和运行。
JDK for ARM平台包括JavaFx的基础,图形和控件组件。3、主要特征
JavaFX中包含以下功能-
- JavaFX是用Java编写的,JavaFX应用程序代码可以从任何Java库引用API。
- JavaFX应用程序的外观和感觉可以定制。因此可以使用级联样式表(CSS)来对JavaFX应用程序进行风格化。平面设计师可以通过CSS自定义外观和样式。
- 还可以在FXML脚本语言中描述UI的表示方面,并使用Java对应用程序逻辑进行编码。
- 通过使用JavaFX Scene Builder,可以通过拖放来设计Ul。Scene Builder将创建可以移植到集成开发环境(IDE)的FXML标记,以便开发人员可以添加业务逻辑。
- JavaFX有一个称为WebView的控件,可以呈现复杂的网页。WebView支持JavaScript,我们可以从Java API在Web页面中调用Javascript。 WebView不支持额外的HTML5功能,包括Web套接字,Web Workers和Web字体,还可以从WebView打印网页。
- Swing互操作性。现有的Swing应用程序可以使用JavaFX类,例如图表和WebView。还可以使用SwingNode类将Swing内容嵌入到我们应用程序中。
- 3D图形功能。JavaFX支持Shape,如Box,Cylinder,MeshView和Sphere子类,SubScene,Material,PickResult,AmbientLight和PointLight。
- Canvas API。 使用Canvas API,可以在JavaFX场景上绘制。
- 打印APl。 javafx.print包提供了JavaFX Printing API的类。
- 富文本支持。JavaFX支持增强的文本,包括双向文本和复杂的文本脚本,例如泰语和印度教的控件,以及多行,多种风格的文本。
- 多点触控支持,JavaFX提供对多点触摸操作的支持。
- JavaFX支持Hi-DPI显示。
4、UI控件
以下列出了JavaFX API中提供的一些内置JavaFX UI控件:
- Label
- Button
- Radio Button
- Toggle Button
- Checkbox
- ChoiceBox
- Text Field
- Password Field
- Scroll Bar
- Scroll Pane
- List View
- Table View
- Tree View
- Tree Table View
- Combo Box
- Separator
- Slider
- Progress Bar
- Progress Indicator
- Hyperlink
- Tooltip
- HTML Editor
- Titled Pane
- AccordionMenu
- Color Picker
- Date Picker
- Pagination Control
- File Chooser
JavaFX允许UI控制节点和形状节点在场景图上共存。
我们可以像任何其他JavaFX节点一样处理任何UI控件,例如可以缩放,旋转,样式和添加效果。二、JavaFx概述
1、JavaFx结构图
一般来说,JavaFX应用程序包含一个或多个对应于窗口的阶段。每个阶段都有一个场景。每个场景都可以有一个控件、布局等附加到它的对象图,称为场景图。这些概念都将在后面更详细地解释。下面是JavaFX应用程序的般结构的图示:
2、JavaFx组件
(1)舞台
舞台是JavaFX应用程序的外部框架。舞台通常对应于一个窗口。在 JavaFX 可以在浏览器中运行的早期阶段,舞台还可以指网页内 JavaFX 可用于绘制自身的区域。
由于 Java 浏览器插件的弃用,JavaFX 主要用于桌面应用程序。在这里,JavaFX 取代了 Swing 作为推荐的桌面GUI 框架。而且JavaFX 看起来比 Swing 更加一致且功能丰富。
在桌面环境中使用时,JavaFX 应用程序可以打开多个窗口。每个窗口都有自己的舞台。
每个阶段都由StageJavaFX 应用程序中的一个对象表示。StageJavaFX 应用程序有一个由JavaFX 运行时为您创建的主对象。如果 JavaFX 应用程序Stage需要打开其他窗口,它可以创建其他对象。例如,对于对话框、向导等。(2)场景
要在JavaFX 应用程序的舞台上显示何内容,您需要一个场景。一个舞台一次只能显示一个场景,但可以在运行时交换场景。就像剧院中的舞台可以重新安排以在戏剧期间显示多个场景一样,JavaFX 中的舞台对象可以在JavaFX 应用程序的生命周期内显示多个场景 (一次一个) 。
您可能想知道为什么 JavaFX 应用程序的每个阶段会有多个场景。想象一个电脑游戏。一个游戏可能有多个“屏幕”向用户显示。例如,初始菜单屏幕、主游戏屏幕(玩游戏的地方)、游戏结束屏幕和高分屏幕。这些屏幕中的每一个都可以由不同的场景来表示。当游戏需要从一屏切换到下一屏时,它只需将相应的场景附加到StageJavaFX 应用程序的对象上即可。
场景由SceneJavaFX 应用程序中的对象表示。JavaFX 应用程序必须创建Scene它需要的所有对象。① 场景图
所有视觉组件(控件、布局等)都必须附加到要显示的场景,并且该场景必须附加到舞台才能使整个场景可见。附加到场景的所有控件、布局等的总对象图称为场景图。
② 节点
附加到场景图的所有组件都称为节点。所有节点都是JavaFX 类的子类,称为javafx.scene.Node。
有两种类型的节点:分支节点和叶节点。分支节点是可以包合其他节点(子节点)的节点。分支节点也称为父节点,因为它们可以包含子节点。叶节点是不能包含其他节点的节点。(3)控件
JavaFX 控件是 JavaFX 组件,它们在JavaFX 应用程序中提供某种控制功能。例如,按钮、单选按钮、表格、树
为了使控件可见,它必须附加到某个Scene对象的场景图中。
控件通常嵌套在一些 JavaFX 布局组件中,这些组件管理控件相对于彼此的布局。
JavaFX 包含以下控件:- 手风琴
- 按钮
- 复选框
- 选择框
- 选色器
- 组合框
- 日期选择器
- 标签
- 列表显示
- 菜单
- 菜单栏
- 密码字段
- 进度条
- 单选按钮
- 滑块
- 微调器
- 拆分菜单按钮
- 拆分窗格
- 表视图
- 选项卡窗格
- 文本区域
- 文本域
- 标题窗格
- 切换按钮
- 工具栏
- 树表视图
- 树视图
这些控件中的每一个都将在单独的文本中进行解释。
(4)布局
JavaFX 布局是其中包含其他组件的组件。布局组件管理嵌套在其中的组件的布局。JavaFX 布局组件有时也称为父组件,因为它们包含子组件,而且布局组件是JavaFX 类的子类javafx.scene.Parent。
布局组件必须附加到某个Scene对象的场景图才能可见。
JavaFX 包含以下布局组件:- 团体
- 地区
- 窗格
- HBox
- 盒子
- 流窗格
- 边框窗格
- 边框窗格
- 堆栈窗格
- 瓷砖窗格
- 网格窗格
- 锚点窗格
- 文本流
这些布局组件中的每一个都将在单独的文本中进行介绍。
(5)图表
JavaFX 带有一组内置的即用型图表组件,因此您不必每次需要基本图表时都从头开始编写图表代码。
JavaFX 包含以下图表组件:- 面积图
- 条形图
- 气泡图
- 折线图
- 饼形图
- 散点图
- 堆积面积图
- 堆积条形图
(6)2D图形
JavaFX 包含可以轻松在屏幕上绘制2D 图形的功能。
(7)3D图形
JavaFX 包含可以轻松在屏幕上绘制 3D 图形的功能。
(8)声音
JavaFX 包含使在 JavaFX 应用程序中播放音频变得容易的功能。这通常在游戏或教育应用中很有用。
(9)视频
JavaFX 包合使在 JavaFX 应用程序中播放视频变得容易的功能。这通常在流媒体应用程序、游戏或教育应用程序中很有用。
JavaFX 包含一个WebView能够显示网页 (HTML5、CSS 等)的组件。JavaFXWebView组件基于 WebKit-Chrome 和 Safari 中也使用的网页染引擎。
该WebView组件使得将桌面应用程序与 Web 应用程序混合成为可能。有时这很有用。例如,如果您已经有一个不错的 Web 应用程序,但需要一些只有桌面应用程序才能提供的功能一一例如磁盘访问、与 HTTP 以外的其他网络协议 (例如 UDP、IAP 等) 的通信。三、JavaFx快速入门
JavaFx中文官方网站:https://openjfx.cn/
1、IDEA配置JavaFx环境
JDK8集成了JavaFx,而JDK11后就不自带JavaFx了,需要自己下载jar包进行导入。
如果使用的是Java8,请直接跳到下面第二步。2、编码与运行
创建以下包目录结构、主入口Main类:
编写一个JavaFx基本结构代码:import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; // 继承Application抽象类,重新start方法 public class Main extends Application { public static void main(String[] args) { // 入口函数里调用Application的静态方法launch,之后会自动调用start方法 Application.launch(args); } /** * @param primaryStage 主窗口 */ @Override public void start(Stage primaryStage) throws Exception { // 设置一个场景,场景里添加一个树形组件图,先创建一个标签 Label label = new Label("Hello JavaFx!"); // 创建布局,将标签放入布局里,BorderPane布局把场景划分为上下左右中,默认加入的控件在中间位置 BorderPane pane = new BorderPane(label); // 创建场景,将布局放入场景里,设置宽度和高度 Scene scene = new Scene(pane, 300, 300); // 将场景设置到窗口里 primaryStage.setScene(scene); // 设置标题 primaryStage.setTitle("我是窗口"); primaryStage.show(); } }
运行main方法,测试结果:
四、组件功能介绍
1、Application
- Application是JavaFx程序的入口,任何JavaFx应用程序程序都要继承该类并重写start()方法。
public class Main extends javafx.application.Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) throws Exception { } }
- 通过main()执行Application的launch(String… args)方法,当然该方法不传入任何值也是可以执行的。launch()方法会默认执行本类下的init()、start()、stop()方法。执行下面的main()方法后显示顺序为:
import javafx.application.Application; import javafx.stage.Stage; public class Main extends Application { public static void main(String[] args) { launch(args); System.out.println("这是main方法"); } @Override public void init() { System.out.println("这是初始化方法"); } @Override public void start(Stage primaryStage) throws Exception { primaryStage.show(); System.out.println("这是start()方法"); } @Override public void stop() throws Exception { System.out.println("这个是stop()方法"); } }
可以看出只有当stop()方法被调用时(即Application应用程序被正常关闭,也可以是图形界面右上角的❌被点击时),launch()方法才执行完毕。(通过Platform.exit()退出界面也是属于正常退出)
通过IDE控制台终止应用程序属于非正常终止,它是通过关闭JVM从而关闭应用程序的。- 也可以在其他类中的main()方法中调用launch()方法,但要传入相应的参数,第一个参数指定一个Application的子类,从而调用该类下的init()、start()、stop()方法,第二个参数制定一个String类型的值。
该方法launch(Class
2、Scene Builder里构建fxml布局文件
官方下载链接:https://openjfx.cn/scene-builder/
点击下一步,完成安装
选择空项目
布局和组件直接拖拽进场景即可,保存后可生成对应的fxml文件。
3、Controller里的initialize方法
有时我们是无法在fxml文件里填充数据的,并且有些内容需要初始化时就填充(如表格),而不是触发事件后填充,此时就可以使用initialize方法,做一些初始化的工作。
initialize()方法需要自定义,定义完之后会自动调用,该方法调用的时机是加载好fxml文件,并绑定好控件id之后,才会自动调用一次。
需要注意的是在initialize()方法中是无法访问Scene场景的。
- 演示案例:使用initialize()方法初始化时填充完TableView的数据。
public class Main extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) throws Exception { Pane root = FXMLLoader.load(getClass().getResource("hello.fxml")); primaryStage.setScene(new Scene(root)); primaryStage.show(); } } public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public class Controller { @FXML private TableView tableView; @FXML private TableColumn name; @FXML private TableColumn age; public void initialize() { ObservableList cellDate = FXCollections.observableArrayList(); name.setCellValueFactory(new PropertyValueFactory("name")); age.setCellValueFactory(new PropertyValueFactory("age")); cellDate.add(new Person("张三", 18)); cellDate.add(new Person("李四", 19)); cellDate.add(new Person("王五", 23)); cellDate.add(new Person("赵六", 15)); tableView.setItems(cellDate); } }
效果图:
4、在Application里操作Controller
- 案例演示:和之前圆的案例一样,要求圆的中心点自适应边框大小,使用fxml实现。
public class JavaFxApplication extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws IOException { FXMLLoader fxmlLoader = new FXMLLoader(); // 使用FXMLLoader获取布局里面的Controller的引用 fxmlLoader.setLocation(getClass().getResource("hello.fxml")); Parent root = fxmlLoader.load(); Scene scene = new Scene(root); // 在Application中操作Controller进行属性绑定 Controller controller = fxmlLoader.getController(); controller.circleLocationBind(scene); primaryStage.setScene(scene); primaryStage.show(); } } public class Controller { @FXML private Circle ci; public void circleLocationBind(Scene scene) { // 获得X和Y中心点的可绑定对象,设置中心点自适应边框大小 ci.centerXProperty().bind(scene.widthProperty().divide(2)); ci.centerYProperty().bind(scene.heightProperty().divide(2)); } }
效果图:
六、JavaFx多线程操作Platform.runLater
当我们执行一些耗时操作时,如加载资源。我们为了防止这些耗时操作占用JavaFx的主线程资源,下面的代码无法执行造成软件界面加载卡顿,我们通常使用JavaFx支持的多线程操作来解决这个问题。
- 案例演示1:使用多线程技术实现点击Button按钮获取姓名数据(模拟数据库获取数据)显示在Label文字布局上。
public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws Exception { Label label = new Label("姓名是?"); label.setLayoutX(200); label.setLayoutY(350); Button button = new Button("点击获取姓名"); button.setLayoutX(200); button.setLayoutY(400); button.setOnAction(event -> { new Thread(() -> { String name = "Aizen"; // 模拟数据库获取值的操作,这里直接定义 label.setText(name); // 更新UI控件的操作 }).start(); }); AnchorPane pane = new AnchorPane(); pane.getChildren().addAll(label, button); Scene scene = new Scene(pane, 500, 500); primaryStage.setScene(scene); primaryStage.show(); } }
如果直接这样运行,点击后会报出非法状态异常,不在JavaFx的Application线程中,更新UI控件必须在Fx Application主线程中。
想要避免这个问题,需要使用到JavaFx提供的静态方法Platform.runLater(Runnable runnable),其中参数需要一个Runnber对象,runLater方法将Runnable放在任务队列里面,在Application线程空闲的时候,会执行队列里的任务。
public class Main0 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws Exception { Label label = new Label("姓名是?"); label.setLayoutX(200); label.setLayoutY(350); Button button = new Button("点击获取姓名"); button.setLayoutX(200); button.setLayoutY(400); button.setOnAction(event -> { // 报错案例: /*new Thread(() -> { String name = "Aizen"; // 模拟数据库获取值的操作,这里直接定义 label.setText(name); // 更新UI控件的操作 }).start();*/ // 正确案例: // runLater方法将Runnable放在任务队列里面,在Application线程空闲的时候,会执行队列里的任务 new Thread(() -> { String name = "Aizen"; // 模拟数据库获取值的操作,这里直接定义 Platform.runLater(() -> { label.setText(name); // 更新UI控件的操作 }); }).start(); }); AnchorPane pane = new AnchorPane(); pane.getChildren().addAll(label, button); Scene scene = new Scene(pane, 500, 500); primaryStage.setScene(scene); primaryStage.show(); } }
效果图:
其实在JavaFx很多控件的事件里面都内部调用了runLater()方法,比如下面这个案例:
- 案例演示2:使用多线程技术实现点击Button按钮通过url加载图片,并显示图片和加载进度(模拟耗时操作)。
public class Main1 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws Exception { ImageView imageView = new ImageView(); imageView.setLayoutX(100); imageView.setLayoutY(20); Label label = new Label(); label.setLayoutX(400); label.setLayoutY(350); Button button = new Button("点击获取图片"); button.setLayoutX(400); button.setLayoutY(410); button.setOnAction(event -> { // 通过url加载图片,这种操作可能会比较耗时通常会另开一个线程去执行,而不占用主线程 Thread thread = new Thread(() -> { Image image = new Image("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F0a0caee4-4afd-4fbf-bcf8-8269315c7915%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715148006&t=f254957770daea43b9b1f4cdb6c2c987", true); // 该监听器的changed方法在底层已经封装了Platform.runLater()方法 image.progressProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue
- 案例演示2:使用多线程技术实现点击Button按钮通过url加载图片,并显示图片和加载进度(模拟耗时操作)。
- 案例演示1:使用多线程技术实现点击Button按钮获取姓名数据(模拟数据库获取数据)显示在Label文字布局上。
- 案例演示:和之前圆的案例一样,要求圆的中心点自适应边框大小,使用fxml实现。
还没有评论,来说两句吧...