使用JWebBrowser把html5转成图片

需要jar包

    DJNativeSwing-SWT.jar,DJNativeSwing.jar,

    org.eclipse.swt.win32.win32.x86_64_3.106.2.v20171129-0543.jar,MozillaInterfaces-1.8.1.3.jar

    其中DJNativeSwing地址

        github:https://github.com/Chrriis/DJ-Native-Swing

        http://mvnrepository.com/tags/maven中也可以搜索到

运行环境

    tomcat中间件

说明

    本人是使用java的定时任务定时把一个列表对象中的属性url(即h5)进行循环,然后把h5转成图片

遇到问题

    1,h5中有ajax请求,使用JWebBrowser的getLoadingProgress方法判断网页的加载状态,进而输出图片时,图片的内容有误

        解决思路ajax请求结束后定会改变视图,可以往JWebBrowser中注入js代码,获取视图的状态,我这里是通过获取jiaz加载条的display属性来判断ajax是否加载完整,具体是java获取js代码返回的值进行递归判断,如果ajax不改变视图,则无需担心。

    2,循环列表对象时,报错,能力有限,真正的原因我也不清楚

         解决办法是把循环操作放在NativeInterface.open()之后,NativeInterface.runEventPump()之前

         如果每次循环都进行open和runEventPump操作会报错的,好像是open和runEventPump是单线程的

         别人的答案(http://topic.csdn.net/u/20110113/11/da8eca94-add0-490d-ab64-f76bd8ba46fa.html):

             因为NativeInterface.open();和NativeInterface.runEventPump();是静态方法,

             猜想只有在程序的开始和结束调用这两个方法,不应该在循环里调用这两个方法

    3,如果h5页面大小不一致,可以通过jWebBrowser.setBounds(0, 0, 470, 340)来进行修改,这是jWebBrowser的尺寸,Jframe的chix尺寸要比jWebBrowser的尺寸略多一点

代码

    1,列表对象循环的代码

	public static void initMainView2(List list) { 
		UIUtils.setPreferredLookAndFeel();    
		NativeInterface.open();  
		
		ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
		for (PadFinanceIndexMenu padFinanceIndexMenu : list) {
			final String classify = padFinanceIndexMenu.getClassify();
			final String type = padFinanceIndexMenu.getType();
			final String url = padFinanceIndexMenu.getUrl();
			final String id = padFinanceIndexMenu.getId();
			
			cacheThreadPool.execute(new Runnable() {
				@Override
				public void run() {
					EventQueue.invokeLater(new Runnable() {  
						public void run() {  
							try {  
								if("市值管理".equals(classify)){
									MainViewSZGL frame = new MainViewSZGL(url, id);  
									frame.setVisible(true);
								} else if("组织人事".equals(classify)){
									MainViewZZRS frame = new MainViewZZRS(url, id);  
									frame.setVisible(true);
								} else {
									if(type.equals("1")){
										MainViewCHH1 frame = new MainViewCHH1(url, id);  
										frame.setVisible(true);  
									} else if(type.equals("2")){
										MainViewCHH2 frame = new MainViewCHH2(url, id);  
										frame.setVisible(true);  
									} else if(type.equals("3")){
										MainViewCHH3 frame = new MainViewCHH3(url, id);  
										frame.setVisible(true);  
									}
								}
							} catch (Exception e) {}  
						}  
					});
				}
			});
			
			try {Thread.sleep(10000);} catch (InterruptedException e) {}
		}
		
		NativeInterface.runEventPump();  
	}

    注释:MainView**对象是不同的JFrame类,因为我这边的h5尺寸很多都不一样;其中cacheThreadPool.execute不知道是不是     多余的,对多线程不熟悉;Thread.sleep(10000)是当前JFrame从加载h5到转图片成功需要的时间预估值,如果不加,会瞬间出现N个JFrame,你懂的;

    2,JFrame类代码,只展示一个,即MainViewCHH1类

import java.awt.Color;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

import chrriis.dj.nativeswing.swtimpl.NativeComponent;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserAdapter;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserEvent;

import com.aliyun.oss.utils.OSSUploadUtils;
import com.thinkgem.jeesite.common.config.Global;

public class MainViewCHH1 extends JFrame{

    private JPanel contentPane;  
    final static public String LS = System.getProperty("line.separator", "/n"); // 行分隔符  
    final static public String FS = System.getProperty("file.separator", "//"); // 文件分割符  
    static StringBuffer jsDimension = new StringBuffer(); // 以javascript脚本获得网页全屏后大小  
    static StringBuffer jsDimension2 = new StringBuffer(); // 以javascript脚本获得网页全屏后大小  
    
    private static final long serialVersionUID = 4859858380825456963L;  
    
    static {  
        jsDimension = new StringBuffer();  
        jsDimension.append("var width = 0;").append(LS);  
        jsDimension.append("var height = 0;").append(LS);  
        jsDimension.append("if(document.documentElement) {").append(LS);  
        jsDimension.append("  width = Math.max(width, document.documentElement.scrollWidth);").append(LS);  
        jsDimension.append("  height = Math.max(height, document.documentElement.scrollHeight);").append(LS);  
        jsDimension.append("}").append(LS);  
        jsDimension.append("if(self.innerWidth) {").append(LS);  
        jsDimension.append("  width = Math.max(width, self.innerWidth);").append(LS);  
        jsDimension.append("  height = Math.max(height, self.innerHeight);").append(LS);  
        jsDimension.append("}").append(LS);  
        jsDimension.append("if(document.body.scrollWidth) {").append(LS);  
        jsDimension.append("  width = Math.max(width, document.body.scrollWidth);").append(LS);  
        jsDimension.append("  height = Math.max(height, document.body.scrollHeight);").append(LS);  
        jsDimension.append("}").append(LS);  
        jsDimension.append("return width + ':' + height;");  
        
        jsDimension2 = new StringBuffer(); 
        jsDimension2.append("var loadingSpinner = document.getElementById('loadingSpinner');").append(LS);  
        jsDimension2.append("var computedStyle = document.defaultView.getComputedStyle(loadingSpinner, null);").append(LS);  
        jsDimension2.append("return computedStyle.display;");  
    }
    
    private boolean display(JWebBrowser jWebBrowser){
		String display = (String) jWebBrowser.executeJavascriptWithResult(jsDimension2.toString()); 
		if(display.equals("block")) {
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			display(jWebBrowser);
		}
		
		return true;
    }
    
    public MainViewCHH1(String url, final String id) {  
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        setBounds(200, 100, 960, 380);  
        contentPane = new JPanel();  
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));  
        setContentPane(contentPane);  
        contentPane.setLayout(null);  
        
        final JWebBrowser jWebBrowser = new JWebBrowser();  
        jWebBrowser.setBounds(0, 0, 940, 340);  
        jWebBrowser.navigate(url);  
        jWebBrowser.setButtonBarVisible(false);    
        jWebBrowser.setMenuBarVisible(false);    
        jWebBrowser.setBarsVisible(false);    
        jWebBrowser.setStatusBarVisible(false);  
        jWebBrowser.addWebBrowserListener(new WebBrowserAdapter() {
        	@Override
        	public void loadingProgressChanged(WebBrowserEvent e) {
        		if (e.getWebBrowser().getLoadingProgress() == 100) {
        			if(display(jWebBrowser)) {
                        NativeComponent nativeComponent = jWebBrowser.getNativeComponent();  
                        nativeComponent.setBackground(Color.blue);
                        Dimension originalSize = nativeComponent.getSize();  
                        BufferedImage image = new BufferedImage(originalSize.width, originalSize.height, BufferedImage.TYPE_INT_RGB);  
                        nativeComponent.paintComponent(image);
                        nativeComponent.setSize(originalSize); 
            			try {
            				String path = Global.getConfig("window.path") + "/finance_chh/" + id + ".png";
                            ImageIO.write(image, "png", new File(path));  
                            OSSUploadUtils.uploadByInputStream(new FileInputStream(new File(path)), "ggkb/cwdhsy/" + id + ".png");
            			} catch (IOException ex) {  
                            ex.printStackTrace();  
                        }  
            			dispose();
        			}
        		}
        	}
		});
        contentPane.add(jWebBrowser);  
    } 
}

    注释:其中80%的代码是前人的,一小部分是自己的;jsDimension2 变量是需要注入的js代码,用于获取id为loadingSpinner的元素的css的display值;display方法是递归操作,判断display的值是否不为block;dispose方法用于关闭JFrame

 

你可能感兴趣的:(使用JWebBrowser把html5转成图片)