需求
定义~, &, ? 三种新运算。
~ a b c = a + b – c
& a b c d e = a + b + c – d – e
? a b c d = a + b – c + d
给定表达式,要求计算结果、解析为正常的算数表达式、构建表达式树并绘制该树形结构。
本文章记录如何绘制树形结构。
考虑到树中一个结点的孩子最多有五个,不便于使用字符串进行绘制。并且要求不能使用TreeView这种横向的控件,只允许从上至下地绘制,所以使用ECharts中的树状图来解决。
思路
JavaFX是一个开源的客户端应用平台,适用于基于Java构建的桌面、移动端和嵌入式系统。可以使用JavaFX绘制图形化界面。ECharts是一款基于JS的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。
JavaFX中的WebView控件可以实现html的展示。所以可以通过java将数据以json的形式储存到文件中,通过html读取并调用ECharts库实现数据的可视化。
实现
JDK的选取
corretto的JDK由于GPL协议的缘故,不支持webkit,所以无法正常使用WebView。
考虑到对webkit的支持以及javaFX库的内置(便于客户配置环境),选择BellSoft的完全版JDK8。要注意,一定要选择完全版,BellSoft标准版JDK8并未内置JavaFX。
图形界面的绘制
使用SceneBuilder生成fxml文件,包括文本输入框、按钮、信息展示用的文本区域、WebView。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.web.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="800.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Program">
<children>
<TextField layoutX="53.0" layoutY="242.0" />
<Button layoutX="120.0" layoutY="385.0" mnemonicParsing="false" text="eval" />
<Text layoutX="53.0" layoutY="58.0" strokeType="OUTSIDE" strokeWidth="0.0" />
<WebView layoutX="287.0" layoutY="113.0" prefHeight="639.0" prefWidth="877.0" />
</children>
</AnchorPane>
拼接json文件
对于一个树形结构,根据ECharts的API,需要提供如下的json数据
{
"name": "~",
"children": [
{
"name": "1",
"children": []
},
{
"name": "2",
"children": []
},
{
"name": "3",
"children": []
}
]
}
可以在树形结构的结点类TreeObject中递归地实现toString()方法来拼接json,并将其储存到文件中
前端展示
将文件的位置视为url,发出ajax请求即可获取json数据,再通过ECharts进行展示
下面是异步请求相关的代码,需要导入jQuery.js
与echarts.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="echarts.js"></script>
<script src="jQuery.js"></script>
</head>
<body>
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="main" style="width: 800px;height:600px;"></div>
<script type="text/javascript">
var data = $.ajax({
url: "dataset.json",//json文件位置,文件名
type: "GET",//请求方式为get
dataType: "json", //返回数据格式为json
async: false,
success: function(data) {//请求成功完成后要执行的方法
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
tooltip: {
trigger: 'item',
triggerOn: 'mousemove'
},
series: [
{
type: 'tree',
data: [data],
left: '2%',
right: '2%',
top: '8%',
bottom: '20%',
symbol: 'emptyCircle',
orient: 'vertical',
expandAndCollapse: true,
label: {
position: 'top',
rotate: 0,
verticalAlign: 'middle',
align: 'right',
fontSize: 22
},
leaves: {
label: {
position: 'bottom',
rotate: 0,
verticalAlign: 'middle',
align: 'left'
}
},
animationDurationUpdate: 750
}
]
};
//设置内容
myChart = echarts.init(document.getElementById('main'));
myChart.setOption(option);
}
});
</script>
</body>
</html>
在java程序中,使用如下代码通过WebView对象获取WebEngine对象
WebEngine engine = webView.getEngine();
可以通过下面的语句加载本地html文件
engine.load(this.getClass().getResource("index.html").toExternalForm());