webview 实现md文档阅读器

在这里插入图片描述

Swing默认html支持

仅支持比如font b u ul li 等等常用呈现内容标签,对于html5扩充的标签不支持,但是如果仅仅通过html标签显示文本的话,影响不是很大. 如果你想要css 来增加’皮肤’ 效果的支持的话,建议放弃在swing中使用吧.


Java中的chrome内核Jcef

chrome释放了v8引擎的内核, nodejs 完成了对v8引擎的包装,
所以有了像nw.js 和 electron.js等这样可以实现GUI页面开发的前端工程.

那么是否可以在Java应用程序中嵌入CEF?
jcef.jar则是对cef的包装,以便在java中可以使用chrome内核, 或者商业化的插件Jxbrowser也是如此 . 金钱的鼓励下,Jxbrowser当然具备

  • 更好的性能
  • 更好的API,
  • bug的维护
  • 产品的迭代
  • 客服的支持等等
<dependency>
		<groupId>com.jcef</groupId>
		<artifactId>jcef</artifactId>
		<version>0.1</version>
		<scope>system</scope>
			<systemPath>${project.basedir}/lib/jcef.jar</systemPath>
	</dependency>

那么通过cef 可以很轻松的解决现在h5 css3的支持问题

 那么选择nodejs的cef和java的cef区别就是, 你更喜欢哪个 

webview希望的转机

JavaFX的webview虽然比不上cef的性能和效果,但是基本的满足还是可以的.
webview 约等于ie11 ,所以你的html能在ie 运行( 不包括使用IE特有的一些windows系统交互内置对象 比如ActiveObject ),那么在webview上也可以轻松展示

可以使用babel 将你的es6代码转换为es5


swing实现md文档阅读器

  1. 实现md转换为html (核心功能)
  2. 实现html 模板页 (UI)
  3. 点击左侧列表, 根据文件信息,获取md2,html内容,替换到html文件
  4. 更新右侧的webview指向最新的html

本篇文章重点是讨论swing的webview

swing代码


import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import com.formdev.flatlaf.FlatLightLaf;
import com.mynote.core.ui.ColorBuilder;
import com.mynote.core.util.FrameUtil;
import com.mynote.core.view.Row;
import com.mynote.example.demo.AbstractDefaultPanel;
import com.mynote.toolkit.markdown.MarkdownEntity;
import com.mynote.toolkit.markdown.MarkdownToHtml;
import com.sun.javafx.application.PlatformImpl;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.URL;

/**
 * author jee
 * webview 让你的swing吸引眼球
 */
@Slf4j
class MdWebViewTest extends AbstractDefaultPanel {

    private String tempDir;

    private WebView webView;

    private JList<String> listDocs;

    private DefaultListModel<String> docModel;


    @Override
    protected void init() {
        createTempDir();
        readMdInDocModel();
        listDocs = new JList<String>(docModel);
    }

    @Override
    protected void render() {
        listDocs.setBackground(ColorBuilder.BG_BLANK_COLOR1);
        listDocs.setForeground(ColorBuilder.LABEL_WHITE_COLOR2);
        JScrollPane scrollPane = new JScrollPane(listDocs);
        scrollPane.setBorder(BorderFactory.createEmptyBorder());
        super.add(scrollPane, "w 15%,h 100%");
        super.add(getWebViewPanel(), "w 85%,h 100%");
    }

    @Override
    protected void bindEvents() {
        listDocs.addListSelectionListener((e) -> {
            JList list = (JList) e.getSource();
            String docFileName = listDocs.getSelectedValue();
            loadMdView(docFileName);
        });
    }

    /**
     * 读取md文件列表 ==>docModel
     */
    private void readMdInDocModel() {
        docModel = new DefaultListModel<String>();
        URL mds = ResourceUtil.getResource("doc/md");
        File mdDir = new File(mds.getFile());
        for (File file : mdDir.listFiles()) {
            docModel.addElement(file.getName());
        }
    }

    /**
     * 获取webview
     */
    private JFXPanel getWebViewPanel() {
        JFXPanel jfxPanel = new JFXPanel();
        PlatformImpl.runLater(() -> {
            webView = new WebView();
            jfxPanel.setScene(new Scene(webView));
            loadMdView(docModel.get(0));
        });
        SwingUtilities.invokeLater(() -> {
            listDocs.setSelectedIndex(0);
        });
        return jfxPanel;
    }


    /**
     * 拷贝至临时目录
     * %user.tmpdir%\tmp-md
     *
     * @return
     */
    private void createTempDir() {
        try {
            String tmp = System.getProperty("java.io.tmpdir");
            File docDir = new File(ResourceUtil.getResource("doc").getFile());
            File tmpMd = new File(tmp + "tmp-md");
            if (!tmpMd.exists()) {
                tmpMd.mkdir();
            } else {
                FileUtils.cleanDirectory(tmpMd);
            }
            log.info("temp目录:", tmpMd);
            FileUtils.copyDirectoryToDirectory(docDir, tmpMd);
            tempDir = tmpMd.getAbsolutePath() + "\\doc\\html";
        } catch (Exception e) {
            log.error("创建临时文件失败:{}", e.getMessage());
            tempDir = null;
        }
    }


    /**
     * md文件 ==> conver html
     */
    private String getMdConvertHtml(String docName, String content) {
        File indexFile = FileUtils.getFile(tempDir, "index.html");
        String indexContext = null;
        try {
            indexContext = FileUtils.readFileToString(indexFile);
            indexContext = indexContext.replace("@{mdBody}", content);
            String htmlFile = docName.replace(".md", ".html");
            File showFile = FileUtils.getFile(tempDir, htmlFile);
            if (!showFile.exists()) {
                log.info("加载md文档:{}", showFile.getPath());
                FileUtils.writeStringToFile(showFile, indexContext);
            }
            return showFile.getAbsolutePath();
        } catch (IOException e) {
            log.error("读取文件异常==>" + e.getMessage());
            return null;
        }

    }

    /**
     * 加载md视图
     */
    private void loadMdView(String docName) {
        Platform.runLater(() -> {
            WebEngine webEngine = webView.getEngine();
            try {
                String mdName = StrUtil.format("doc/md/{}", docName);
                MarkdownEntity mdEntity = MarkdownToHtml.ofFile(mdName);
                if (tempDir != null) {
                    //webView.getEngine().load("http://127.0.0.1:5500/index.html");
                    /*不带样式内容*/
                    webEngine.load("file:///" + getMdConvertHtml(docName, mdEntity.getHtml()));
                } else {
                    /*加载带样式内容*/
                    webEngine.loadContent(mdEntity.toString(), "text/html");
                }
            } catch (IOException e) {
                webEngine.loadContent("加载失败:" + e.getMessage(), "text/html");
            }


        });
    }


    public static void main(String[] args) {
        FlatLightLaf.install();
        FrameUtil.launchTest(new MdWebViewTest());
    }
}


Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐