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文档阅读器
- 实现md转换为html (核心功能)
- 实现html 模板页 (UI)
- 点击左侧列表, 根据文件信息,获取md2,html内容,替换到html文件
- 更新右侧的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());
}
}