进期客户提出在一个Java Swing项目要集成另外2个系统:
1、集成Fine Report(基于Java Web发布的)要能打印、另存pdf|Excel。
2、集成质检报告系统,主要都是基于Web的图片,要能缩放查看。
基于以上2个要求,我们首先想到的是在JavaSwing中的JFrame中能嵌入一个浏览器控件,再通过浏览器加载Web url实现以上2个需求。经过一番搜索,了解到Java FX有Web View实现了浏览器的基本功能,而Java FX的控件需要以交互模式集成到Java Swing中,经过一番努力终于完成。进行测试才发现Java FX的WebView控件功能太弱了,首先在嵌入Fine Report的报表后能正常显示,但是另存、下载、打印都失效了,而且也不能缩放查看图片。最终智能放弃此方案。又重新从网上搜索发现一个控件JxBrowser(付费的),经过一番集成测试,终于在6.5.1版本上实现了以上2个目标,再高的版本是有问题。下面就把封装实现代码分享一下。
1、基于JxBrowser6.5.1封装的浏览器控件(内置破解,仅用于个人学习)。
2、适用于在Java Swing应用中嵌入Web页面,并实现java与javascript的交互。
3、支持嵌入服务器页面,支持页面中的附件下载、报表打印、另存等功能。
4、支持嵌入帆软报表。
5、支持Ctrl+鼠标滚轮实现页面缩放
1、破解文件(src/META-INF/teamdev.licenses),仅供个人学习,力所能及请付费购买(https://www.teamdev.com/jxbrowser)
Product: JxBrowser
Version: 6.x
Licensed to:
License type: Enterprise
License info: JxBrowser License
Expiration date: 01-01-9999
Support expiration date: NO SUPPORT
Generation date: 01-01-1970
Platforms: win32/x86;win32/x64;mac/x86;mac/x64;linux/x86;linux/x64
Company name: TeamDev Ltd.
SigB: 1
SigA: 1
2、封装号的浏览器控件(com.controls.WebBrowser.java)
package com.controls;
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.CloseStatus;
import com.teamdev.jxbrowser.chromium.UnloadDialogParams;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
import com.teamdev.jxbrowser.chromium.swing.DefaultDialogHandler;
/**
* 功能说明:基于jxBrowser的自定义浏览器控件 修改说明:
*
* @author zhenglibing
* @date 2019年7月5日 下午1:58:32
* @version 0.1
*/
public class WebBrowser extends JPanel {
private static final long serialVersionUID = 1L;
private String url = "http://www.baidu.com";
private boolean ZoomingFlag = false; // 是否正在缩放,按下Ctrl键变为true,释放Ctrl键变为false
// 25% : "default_zoom_level": -7.6035680338478615,
// 33% : "default_zoom_level": -6.0311726618503405,
// 50% : "default_zoom_level": -3.8017840169239308,
// 67% : "default_zoom_level": -2.2293886449264093,
// 75% : "default_zoom_level": -1.5778829311823859,
// 90% : "default_zoom_level": -0.5778829311823857,
// 100% : "default_zoom_level": 0.0,
// 110% : "default_zoom_level": 0.5227586988632231,
// 125% : "default_zoom_level": 1.2239010857415449,
// 150% : "default_zoom_level": 2.223901085741545,
// 175% : "default_zoom_level": 3.069389038663465,
// 200% : "default_zoom_level": 3.8017840169239308,
// 250% : "default_zoom_level": 5.025685102665476,
// 300% : "default_zoom_level": 6.025685102665476,
// 400% : "default_zoom_level": 7.6035680338478615,
// 500% : "default_zoom_level": 8.827469119589406
// 定义缩放级别值数组
private double[] levels = { -7.6035680338478615, -6.0311726618503405, -3.8017840169239308, -2.2293886449264093,
-1.5778829311823859, -0.5778829311823857, 0.0, 0.5227586988632231, 1.2239010857415449, 2.223901085741545,
3.069389038663465, 3.8017840169239308, 5.025685102665476, 6.025685102665476, 7.6035680338478615,
8.827469119589406 };
private String[] strLevels = { "25%", "33%", "50%", "67%", "75%", "90%", "100%", "110%", "125%", "150%", "175%",
"200%", "250%", "300%", "400%", "500%" };
private long lastWheelTime = 0; // 最后滚动鼠标滚轮的时间
private Browser browser; // 浏览器对象,需引用jxbrowser
private BrowserView view; // 浏览器视图对象,需引擎jxbrowser
// 以下代码用于破解jxbrowser
static {
try {
Class claz = null;
//6.5.1版本破解 兼容xp
claz = Class.forName("com.teamdev.jxbrowser.chromium.aq");
// 6.21版本破解 默认使用最新的6.21版本
// claz = Class.forName("com.teamdev.jxbrowser.chromium.ba");
// 6.23版本破解
//claz = Class.forName("com.teamdev.jxbrowser.chromium.bb");
Field e = claz.getDeclaredField("e");
Field f = claz.getDeclaredField("f");
e.setAccessible(true);
f.setAccessible(true);
Field modifersField = Field.class.getDeclaredField("modifiers");
modifersField.setAccessible(true);
modifersField.setInt(e, e.getModifiers() & ~Modifier.FINAL);
modifersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
e.set(null, new BigInteger("1"));
f.set(null, new BigInteger("1"));
modifersField.setAccessible(false);
} catch (Exception e) {
e.printStackTrace();
System.out.println("执行jxbrowser破解程序时出现异常" + e.getMessage());
}
}
/**
* 默认构造方法
*/
public WebBrowser() {
this.init();
}
/**
* 构造方法重载
*
* @param url
* 浏览器默认加载的url地址
*/
public WebBrowser(String url) {
this.url = url.startsWith("http://") ? url : "http://" + url;
this.init();
}
/**
* 功能说明:初始化jxBrowser 修改说明:
*
* @author zhenglibing
* @date 2019年7月5日 下午2:28:27
*/
private void init() {
this.browser = new Browser();
this.view = new BrowserView(browser);
this.setLayout(new BorderLayout());
this.add(view, BorderLayout.CENTER);
this.browser.loadURL(this.url);
// 以下代码支持鼠标拖拽超链接内容
this.browser.setDialogHandler(new DefaultDialogHandler(view) {
@Override
public CloseStatus onBeforeUnload(UnloadDialogParams params) {
String title = "Confirm Navigation";
String message = params.getMessage();
int returnValue = JOptionPane.showConfirmDialog(view, message, title, JOptionPane.OK_CANCEL_OPTION);
if (returnValue == JOptionPane.OK_OPTION) {
return CloseStatus.OK;
} else {
return CloseStatus.CANCEL;
}
}
});
this.browser.loadHTML(""
+ "Click here to leave"
+ "");
// 以下代码支持Ctrl + 鼠标滚轮实现页面放大缩小
// 注册键盘按下事件
this.view.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
/**
* 键盘按下
*/
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == 17) {
ZoomingFlag = true;
}
}
/**
* 键盘释放
*/
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
System.out.println("keyReleased");
ZoomingFlag = false;
}
});
// 注册鼠标滚轮事件
this.view.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
// System.out.println(e.getScrollAmount());
if (e.getScrollAmount() != 3 || e.getWhen() - lastWheelTime < 20) {
// 滚动太快则过滤一下
// System.out.println("过滤...");
return;
}
// System.out.println("getWhen = " + e.getWhen());
// System.out.println("lastWheelTime = " + lastWheelTime);
if (e.getScrollAmount() == 3 && ZoomingFlag) {
double currZoomLevel = browser.getZoomLevel();
if (e.getWheelRotation() == -1) {
// 加
for (int i = 0; i < levels.length; i++) {
if (currZoomLevel == levels[i]) {
if (i < levels.length - 1) {
browser.setZoomLevel(levels[i + 1]);
System.out.println("当前缩放级别:" + strLevels[i + 1]);
}
break;
}
}
System.out.println("放大");
} else if (e.getWheelRotation() == 1) {
// 减
for (int i = 1; i < levels.length; i++) {
if (currZoomLevel == levels[i]) {
if (i > 0) {
browser.setZoomLevel(levels[i - 1]);
System.out.println("当前缩放级别:" + strLevels[i - 1]);
}
break;
}
}
System.out.println("缩小");
}
// 记录最后一次滚轮时间
if (lastWheelTime != e.getWhen()) {
lastWheelTime = e.getWhen();
}
}
}
});
}
/**
* 功能说明:获取浏览器访问的url地址
* 修改说明:
* @author zhenglibing
* @date 2019年7月9日 下午2:32:39
* @return
*/
public String getURL() {
if (null != this.browser) {
return this.browser.getURL();
}
else
{
return "";
}
}
/**
* 功能说明:swing方法,设置浏览器访问的url地址 修改说明:
*
* @author zhenglibing
* @date 2019年7月5日 下午2:30:13
* @param urlString
*/
public void setURL(final String urlString) {
if (null == urlString || "".equals(urlString)) {
this.browser.loadURL("");
this.browser.loadHTML("");
} else {
String oldUrl = this.browser.getURL();
if (!urlString.equals(oldUrl)) {
this.browser.loadURL(urlString);
} else {
this.browser.reload();
}
}
}
/**
* 功能说明:swing方法,设置浏览器的html内容 修改说明:
*
* @author zhenglibing
* @date 2019年7月5日 下午5:34:12
* @param htmlContent
*/
public void setContent(final String htmlContent) {
this.browser.loadHTML(htmlContent);
}
/**
* 功能说明:swing方法,清空浏览器的内容 修改说明:
*
* @author zhenglibing
* @date 2019年7月5日 下午5:33:42
*/
public void clear() {
this.setURL("");
}
/**
* 功能说明:获取浏览器类型信息 修改说明:
*
* @author zhenglibing
* @date 2019年7月5日 下午5:32:54
* @return
*/
public String getBrowserType() {
return "jxBrowser" + "v6.23.1";
}
/**
* 功能说明:资源释放方法 修改说明:
*
* @author zhenglibing
* @date 2019年7月5日 下午5:33:21
*/
public void dispose() {
}
}
3、测试启动类(com.controls.Start.java)
package com.controls;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Start {
private static String title = "浏览器测试";
private static String url = "https://www.baidu.com";
public static void main(String[] args) {
if (args.length >= 2) {
title = args[0];
url = args[1];
}
else if (args.length == 1) {
url = args[0];
}
JFrame frm = new JFrame(title);
frm.setSize(800,600);
frm.setExtendedState(JFrame.MAXIMIZED_BOTH);
WebBrowser browser = new WebBrowser();
browser.setSize(800, 600);
browser.setVisible(true);
frm.add(browser, BorderLayout.CENTER);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setVisible(true);
browser.setURL(url);
}
}
完整的代码及依赖jar文件下载