J1002.JavaFX简介

JavaFX简介与实践
本文介绍了JavaFX的发展历程,从2008年的第一个版本到2014年的JavaFX 8.0,并讨论了其相对于Swing和SWT的优势与不足。文章详细解释了JavaFX的特点,包括与JDK的整合、丰富的UI组件、数据绑定功能以及事件处理机制。此外,还提供了两个示例程序,展示如何使用JavaFX创建简单的UI应用。

引言

2008年12月05日,SUN发布了JavaFX第一个正式版本,以期望Java在UI端能够更好地应用于开发富客户端的互联网应用(Rich Internet Cliet)。

2011年发布的JavaFX2.0取消之前基于Script的模式,改为使用原生Java结合CSS等进行了重构。

2014年发布的JavaFX8.0,与JDK1.8进行整合,并运用JDK8的新特性。

 

我们在上一篇文章中,已经简要地介绍了JavaUI框架的发展历史及特性。从这篇文章开始介绍JavaFX的特性,使用方法,优缺点以及注意事项等。

 

总体来说,使用JavaFX开发界面,要比Swing、SWT等要快捷一些。但作为一个已经发展了10多年的“主流”Java UI框架,在功能丰富程度以及一些处理细节上,还有比较多的欠缺甚至不方便、官方无解的问题。举几个例子:

1、JavaFX的Alert对话话比Swing提供的好用、漂亮,但是在Swing中使用JavaFX Alert时,由于其各自的派遣线程的问题,无法使用Modal模式。这种问题简直让人抓狂。

2、TableView在样式、某些处理机制方面,同样不可理喻。默认情况下,不管TableView中有多少数据,都会为整个表格绘制表格线;在编辑单元格时,必须敲回车键才能提交修改,如果点击其它单元格、其它行,或者敲Tab键,TableView将自动Cancel修改的内容;提供的TableCell太少,功能太弱。像必须敲回车才能提交修改的问题,开发人员N久以前就作为Bug提交给SUN/Oracle了,有人说JDK9会修复这个问题,但实际上我看了JDK9.0.1中相关的源代码,并没有。开发人员写了几行较详细的注释,说明这个问题不是他的责任,你们自行想办法。

这类问题都留给开发人员自行解决,个人感觉是十分说不过去的。在开发lrJAP平台的过程中,我数次被这样的问题折腾,甚至在日志中写下了这样一段话:

2017-08-25,越来越感觉JavaFX与主流JS(如ExtJS)有差距,今天已经特别想放弃JavaFX,而且特别到一定要把这句话记下来。唉。

 

拔特,问题总是能够被解决的,所以我们继续。先介绍介绍一下JavaFX与JS类框架相比的一些特性。

1、JavaFX已经与JDK融合,理论上可以使用JDK所有功能,以及所有的第三方Java类库,只要资源能够加载到JVM中,JavaFX就可以使用这些资源。这为我们在各方面都提供了便利。并且降低了上手的难度。

2、提供了较丰富的基础UI组件以及布局。特别是BorderPane,有利于界面模式的开发。可以通过CSS进行代码风格控制。

3、提供了基础的数据绑定功能,可以实现View-Model之间的双向数据(属性)绑定,并能够实现较复杂的事件处理机制。简化了与数据展现、控制相关的代码。

4、提供了使用比较方便的事件机制,并且可以与JDK8提供的Lamda结合,简化事件处理的代码。

5、提供了一些基本的图表。如饼图、折线图等。

 

个人感觉,JavaFX比较适用于以下业务场景:

1、基于企业内部局域网的应用,或基于相对比较封闭的网络环境下的集团级应用。也就是应用于传统的企业内部管理、业务系统的开发。

2、适用于业务数据结构复杂、业务处理逻辑复杂、有一定的性能需求,但对界面炫酷程度没有极端要求的应用。

3、功能界面可以被抽象、归类,希望在此基础上,实现快速开发。

 

基于JavaFX的应用如果运行在Internet环境中,则安全、带宽等方面要有相应的保证。个人感觉,对于一般用户来说,使用基于JavaFX的应用,主要困难在于下载、安装、配置JRE,以及基于信任、安全方面的考虑。

 

第一个JavaFX程序:HelloWorld

所有示例程序,除非特别说明,否则一律基于以下主要环境:Win10,IntelliJ IDEA,JDK 1.8_151。

为了能够更清楚地说明代码结构以及处理细节,代码中的注释有点过度:

package com.lirong.javafx.demo;

 

import javafx.application.Application;

import javafx.geometry.Insets;

import javafx.scene.Scene;

import javafx.scene.control.Alert;

import javafx.scene.control.Button;

import javafx.scene.layout.BorderPane;

import javafx.scene.layout.HBox;

import javafx.stage.Stage;

 

public class HelloWorldUI extends Application {

 

private static final double DEFAULT_BUTTOH_HEIGHT = 30;

 

public static void main(String[] args) {

 

// 启动应用

Application.launch(args);

}

 

@Override

public void start(Stage stage) throws Exception {

 

Button buttonHelloWorld = new Button("HelloWorld");

// 设置按钮大小

buttonHelloWorld.setPrefSize(100, DEFAULT_BUTTOH_HEIGHT);

// 事件处理

buttonHelloWorld.setOnAction(action -> {

// 弹出模态对话框

Alert alert = new Alert(Alert.AlertType.INFORMATION);

alert.setContentText("Hello World!");

alert.initOwner(stage);

alert.showAndWait();

});

 

// 用于验证ToolBar中组件之间间隔的按钮,仅显示,无事件处理

Button buttonOther = new Button("Other");

buttonOther.setPrefSize(80, DEFAULT_BUTTOH_HEIGHT);

 

// 模拟工具栏效果

HBox toolBar = new HBox();

// 设置ToolBar中控件与边界上、下、左、右的距离

toolBar.setPadding(new Insets(10));

// 设置ToolBar中控件之间的间隔

toolBar.setSpacing(10);

 

// 为ToolBar增加元素

toolBar.getChildren().addAll(buttonHelloWorld, buttonOther);

 

// 设置最外层的容器

BorderPane container = new BorderPane();

container.setTop(toolBar);

 

// 处理应用场景,默认窗口大小为800*600

Scene scene = new Scene(container, 800, 600);

stage.setTitle("'Hello World' JavaFX Application");

stage.setScene(scene);

stage.show();

}

}

运行效果如下图:

 

与程序逻辑无关的代码量比较少,默认的界面风格还说得过去。

 

第一个JavaFX Embedded in Swing程序

通过JavaFX提供的JFXPanel,可以“较方便”地在Swing程序中使用JavaFX组件。如下代码演示如何在JFrame中显示一个使用JavaFX控件模拟的表单信息:

首先,构造一个4列10行的JavaFX GridPane:

package com.lirong.javafx.demo.j1002.swing;

 

import javafx.geometry.HPos;

import javafx.geometry.Insets;

import javafx.geometry.Pos;

import javafx.scene.control.Label;

import javafx.scene.control.TextField;

import javafx.scene.layout.ColumnConstraints;

import javafx.scene.layout.GridPane;

import javafx.scene.layout.Priority;

 

public class TestGridPaneUI extends GridPane {

 

public TestGridPaneUI() {

 

super();

initUI();

}

 

private void initUI() {

 

// 显示网格线

setGridLinesVisible(Boolean.TRUE);

 

// 设置间隔

setVgap(5);

setHgap(5);

setPadding(new Insets(5));

 

// 设置为4列

ColumnConstraints col1 = new ColumnConstraints();

col1.setPercentWidth(20);

 

ColumnConstraints col2 = new ColumnConstraints();

col2.setPercentWidth(30);

 

ColumnConstraints col3 = new ColumnConstraints();

col3.setPercentWidth(20);

 

ColumnConstraints col4 = new ColumnConstraints();

col4.setPercentWidth(30);

 

getColumnConstraints().addAll(col1, col2, col3, col4);

 

// 填充控件

int row = 0;

int col = 0;

 

while (row < 10) {

 

Label label01 = new Label(String.format("Row-%d,Col-%d:", row + 1, col + 1));

label01.setAlignment(Pos.CENTER_RIGHT);

// 右对齐

GridPane.setHalignment(label01, HPos.RIGHT);

add(label01, col, row);

 

col++;

 

if (col > 3) {

row++;

col = 0;

}

 

TextField text01 = new TextField();

// 填充整个单元格

GridPane.setHgrow(text01, Priority.ALWAYS);

add(text01, col, row);

 

col++;

 

if (col > 3) {

row++;

col = 0;

}

 

Label label02 = new Label(String.format("Row-%d,Col-%d:", row + 1, col + 1));

add(label02, col, row);

// 右对齐

GridPane.setHalignment(label02, HPos.RIGHT);

 

col++;

 

if (col > 3) {

row++;

col = 0;

}

 

TextField text02 = new TextField();

// 填充整个单元格

GridPane.setHgrow(text02, Priority.ALWAYS);

add(text02, col, row);

 

col++;

 

if (col > 3) {

row++;

col = 0;

}

}

}

}

 

然后把这个GridPane显示在JFrame中:

package com.lirong.javafx.demo.j1002.swing;

 

import javafx.embed.swing.JFXPanel;

import javafx.scene.Scene;

import javax.swing.JFrame;

 

public class TestSwingFX {

 

public static void main(String[] args) {

 

JFrame frame = new JFrame();

frame.setTitle("Swing JavaFX Test");

frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

frame.setSize(800, 600);

 

JFXPanel jfxPanel = new JFXPanel();

TestGridPaneUI gridPaneUI = new TestGridPaneUI();

jfxPanel.setScene(new Scene(gridPaneUI));

frame.add(jfxPanel);

frame.setVisible(Boolean.TRUE);

}

}

 

运行效果如下:

 

取消网格线后的效果:

 

关键类为JFXPanel,它是处理Swing和JavaFX界面、事件等交互的中介。

在拖放JFrame时,GridPanel将根据我们设置的比例自动缩放。

 

转载于:https://www.cnblogs.com/yujj-cn/p/7803432.html

D:\基地\Misc工具\Misc工具\Misc工具\stegsolvsndqmd>java -jar Jeecg_Tools-1.0-java8.jar Graphics Device initialization failed for : d3d, sw Error initializing QuantumRenderer: no suitable pipeline found java.lang.RuntimeException: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found at com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:280) at com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:222) at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:260) at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267) at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158) at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658) at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195) at java.base/java.lang.Thread.run(Thread.java:842) Caused by: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:94) at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124) ... 1 more Exception in thread "main" java.lang.RuntimeException: No toolkit found at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:272) at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267) at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158) at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658) at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195) at java.base/java.lang.Thread.run(Thread.java:842)
07-29
[Application] app.mainmodule=app.main/cc.cc1234.Application [JavaOptions] # JDK 17 路径(替换为你的实际路径) java-options=-Djava.home=D:/Bigdata/Java/jdk-17.0.12 # JavaFX 17.0.15 配置(关键!指向解压后的 lib 目录) java-options=-p D:/Bigdata/Java/javafx-sdk-17.0.15/lib java-options=--add-modules=javafx.controls,javafx.fxml,javafx.graphics # ZGC 垃圾回收器配置(JDK 17 已支持,无需实验性选项) java-options=-XX:+UseZGC java-options=-Xmx4g java-options=-XX:MetaspaceSize=64m java-options=-XX:MaxMetaspaceSize=256m # 基础配置 java-options=-Dfile.encoding=utf-8 java-options=-Djdk.gtk.version=2 # JFoenix 库模块导出(保留,确保界面组件正常加载) java-options=--add-exports=javafx.controls/com.sun.javafx.scene.control.behavior=com.jfoenix java-options=--add-exports=javafx.base/com.sun.javafx.binding=com.jfoenix java-options=--add-exports=javafx.base/com.sun.javafx.event=com.jfoenix java-options=--add-exports=javafx.graphics/com.sun.javafx.stage=com.jfoenix java-options=--add-exports=javafx.graphics/com.sun.javafx.scene=com.jfoenix java-options=--add-exports=javafx.graphics/com.sun.javafx.geom=com.jfoenix java-options=--add-exports=javafx.graphics/com.sun.javafx.scene.text=com.jfoenix java-options=--add-exports=javafx.controls/com.sun.javafx.scene.control.inputmap=com.jfoenix java-options=--add-exports=javafx.graphics/com.sun.javafx.scene.traversal=com.jfoenix java-options=--add-exports=javafx.controls/com.sun.javafx.scene.control=com.jfoenix java-options=--add-exports=javafx.graphics/com.sun.javafx.util=com.jfoenix java-options=--add-opens=java.base/java.lang.reflect=com.jfoenix # (可选)GC 日志输出(调试用,启动成功后可注释) # java-options=-Xlog:gc*:file=./gc.log:time,uptime 改成这样行不行
06-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值