前言
我们知道web 的UI界面真得很漂亮,而且开源社区有很多插件可以用,所以要开发出漂亮的页面也很容易。那么,我们使用SWT/JFace进行桌面软件的开发时,也想要实现一些像JQuery EasyUI等等漂亮的表格,可以说是非常难。但是,SWT Browser 是 Eclipse SWT 的标准部件,它提供了把 HTML 整合到 Java 平台的能力。该部件植入了平台流行的 HTML 渲染引擎:在 Microsoft Windows 平台上是 IE,在 Linux 平台上是 Mozilla,在 Apple Mac 平台上是 Safari。但在实现的过程中还是有很多很坑的,笔者在网上搜了很多资料,都太简略,没什么干货。所以,只能自己摸索。废话不多说,我们直接干吧!
一. 创建简单的浏览器
import org.eclipse.swt.*;
import org.eclipse.swt.browser.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
public class SimpleBrowser {
public static void main(String [] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Browser browser;
try {
browser = new Browser(shell, SWT.NONE);
} catch (SWTError e) {
System.out.println("Could not instantiate Browser: " + e.getMessage());
display.dispose();
return;
}
browser.setUrl("www.baidu.com");
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
效果如下:
二、java运行js代码
final String js = "document.write('hello world')";
browser.addProgressListener(new ProgressListener() {
@Override
public void changed(ProgressEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void completed(ProgressEvent arg0) {
browser.execute(js);
}
});
js为javaScript代码,不过不建议在java代码中运行js,建议在HTML引入js源文件。为什么?因为Java代码运行js有很多你想不到的坑。包括你用File去读取js文件取字符串来执行,会遇到加载失败,但不会报错!嗯,所以大家忘了这种方法吧,后面我会讲我喜欢用的方法。
三、HTML与java交互
1. BrowserFunction介绍
BrowserFunction 可以实现java与js的交互,它的构造函数是 BrowserFunction(browser:Browser, name:String),其中 browser 代表 Browser 对象,而 name 则代表绑定该浏览器的 JavaScript 方法名,定义了该 BrowserFunction 对象以后,任何在 Browser 显示的网页,都可以访问名为 name 的 JavaScript 方法。BrowserFunction 只有一个接口 public Object function(Object[] arguments),它接收网页传来的参数,执行 Java 代码返回结果对象。完整代码在GitHub:https://github.com/OysterView/SWT_Browser_JQuery
java代码中加入:
String fileName = "H:\\project\\GUI_Test\\html2\\demo1\\demo1.html";
String html1 = FileUtils.readFileToString(new File(fileName));
browser.setText(html1);
new BrowserFunction(browser, "get") {
@Override
public Object function(Object[] arguments) {
System.out.println("get: " + ((String) arguments[0]));
return new String[] { "666", "777", "888" };
}
};
HTML代码中,注意JS中不要有注释(这个坑搞了我好久!!!),不然会出错,原因我也不知道,可能是SWT的解析有问题吧。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>demo1</title>
<script type="text/javascript">
function display(){
var returnFromJavaArray = get("666");
document.getElementById("demo").innerHTML = returnFromJavaArray[0]+returnFromJavaArray[1];
}
</script>
</head>
<body>
<p>点击按钮执行 <em>display</em> 函数.</p>
<button onclick="display()">点这里</button>
<p id="demo">777</p>
</body>
</html>
效果:
按下按钮就js调用get(“666”),传参数“666”给java,然后Java返回String数组:js获取数组然后显示出来!
好!至此,我们已经实现了java与HTML通过js交互了。
四、使用JQuery组件
java代码(Demo2.java)
package com.oysterview.frame;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import com.alibaba.fastjson.JSON;
import com.oysterview.util.FileUtils;
public class Demo2 {
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Browser browser;
try {
browser = new Browser(shell, SWT.NONE);
} catch (SWTError e) {
System.out.println("Could not instantiate Browser: " + e.getMessage());
display.dispose();
return;
}
String fileName = "E:\\Project\\Java\\SWT_Browser_JQuery\\html\\demo2\\demo2.html";
String html1 = FileUtils.readFileToString(new File(fileName));
browser.setText(html1);
new BrowserFunction(browser, "getDataFromJava") {
@Override
public Object function(Object[] arguments) {
// System.out.println("get: " + ((String) arguments[0]));
List<TableData> list = new ArrayList<>();
Random random = new Random();
for(int i=0;i<1000;i++){
int amount = random.nextInt(100);
int price = random.nextInt(5);
TableData tableData = new TableData();
tableData.inv = i+"";
tableData.date = new Date().toString();
tableData.name = "name"+i;
tableData.amount = amount;
tableData.price = price;
tableData.cost = price*amount;
tableData.note = "note"+i;
list.add(tableData);
}
String jsonString = JSON.toJSONString(list);
System.out.println(jsonString);
return jsonString;
}
};
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static class TableData{
String inv;
String date;
String name;
int amount;
int price;
int cost;
String note;
public String getInv() {
return inv;
}
public void setInv(String inv) {
this.inv = inv;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
}
HTML代码(demo2.html):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="keywords" content="jquery,ui,easy,easyui,web">
<meta name="description" content="easyui help you build your web page easily!">
<title>DataGrid Virtual Scrolling - jQuery EasyUI Demo</title>
<!-- 注意这里要使用绝对路径,为什么不用相对路径?我也不知道,用相对路径用chrome可以正常运行,
但是SWT却不可以,坑了我很久!可能是SWT的BUG,当然你也可以使用URL,但是URL要联网 -->
<link rel="stylesheet" type="text/css" href="E:\\Project\\Java\\SWT_Browser_JQuery\\html\\demo2\\jquery-easyui-1.9.4/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="E:\\Project\\Java\\SWT_Browser_JQuery\\html\\demo2\\jquery-easyui-1.9.4/themes/icon.css">
<link rel="stylesheet" type="text/css" href="E:\\Project\\Java\\SWT_Browser_JQuery\\html\\demo2\\jquery-easyui-1.9.4/demo/demo.css">
<script type="text/javascript" src="E:\\Project\\Java\\SWT_Browser_JQuery\\html\\demo2\\jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="E:\\Project\\Java\\SWT_Browser_JQuery\\html\\demo2\\jquery.easyui.min.js"></script>
<!-- 支持显示海量数据插件datagrid-scrollview.js, 要匹配jquery.easyui.min.js和jquery.min.js版本,不然会有问题-->
<script type="text/javascript" src="E:\\Project\\Java\\SWT_Browser_JQuery\\html\\demo2\\datagrid-scrollview.js"></script>
<script type="text/javascript" src="E:\\Project\\Java\\SWT_Browser_JQuery\\html\\demo2\\demo2.js"></script>
<!-- 以下是用URL的例子 -->
<!-- <link rel="stylesheet" type="text/css" href="http://www.w3cschool.cc/try/jeasyui/themes/default/easyui.css"> -->
<!-- <link rel="stylesheet" type="text/css" href="http://www.w3cschool.cc/try/jeasyui/themes/icon.css"> -->
<!-- <link rel="stylesheet" type="text/css" href="http://www.w3cschool.cc/try/jeasyui/demo/demo.css"> -->
<!-- <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script> -->
<!-- <script type="text/javascript" src="http://www.w3cschool.cc/try/jeasyui/jquery.easyui.min.js"></script> -->
<style type="text/css">
.datagrid-header-rownumber,.datagrid-cell-rownumber{
width:40px;
}
</style>
</head>
<body>
<h2>DataGrid Virtual Scroll View Demo<-----> 支持显示海量数据</h2>
<div class="demo-info" style="margin-bottom:10px">
<div class="demo-tip icon-tip"> </div>
<div>Drag the vertical scroll and release it to navigate to the desired page.</div>
</div>
<table id="tt" class="easyui-datagrid" style="width:1000px;height:700px"
title="DataGrid - VirtualScrollView"
data-options="view:scrollview,rownumbers:true,singleSelect:true,
autoRowHeight:false,pageSize:50">
<thead>
<tr>
<th field="inv" width="80">Inv No</th>
<th field="date" width="250">Date</th>
<th field="name" width="80">Name</th>
<th field="amount" width="80" align="right">Amount</th>
<th field="price" width="80" align="right">Price</th>
<th field="cost" width="100" align="right">Cost</th>
<th field="note" width="110">Note</th>
</tr>
</thead>
</table>
<button id = 'button' type="button" onclick="loadData()">从JAVA加载数据</button>
<p id="demo">777</p>
</body>
</html>
js代码(demo2.js):
function loadData(){
//在js文件可以注释没有问题,可能HTML在加载的时候会处理吧,但不要在HTML里面写js的时候写注释,会有问题
var datas = getDataFromJava("666");
//从java拿到的是一个json string,需要把它转化为json object
var dataJson = $.parseJSON( datas );
$('#tt').datagrid('loadData', dataJson);
$("#demo").text("总行数:"+$('#tt').datagrid('getData')['total']);
$('#tt').datagrid('scrollTo',$('#tt').datagrid('getData')['total']-1);
}
效果:
五、总结
1. HTML文件中引入js和css文件时要用绝对路径
2. 建议js代码不要HTML文件中,因为如果你有注释的话,会出错,而且出错了,也不会IDE也不会报错,比较难调试
3. 数据交互用JsonString
4. 调试的时候,建议先在chrome上面调试好,因为浏览器的开发工具比较好调试,然后如果有跟Java数据交互了,再嵌入到Java中进行调试
5. 本文的代码可以在github中找到:https://github.com/OysterView/SWT_Browser_JQuery 祝你好运!