基于 Java 和 Bytemd 用 120 行代码实现一个桌面版 Markdown 编辑器
使用 Swin
g 并且成功了的方案最知名的就是 JetBrains 全家桶。目前来看,为了解决这个"丑"的问题,现在有比较简单的处理方案:
方案一:使用 compose-jb(名字有点不好听,官方仓库为 https://github.com/JetBrains/compose-jb)开发,这个是 JetBrains 系列的通用组件,基于 Swing 做二次封装,「不过必须使用语言 Kotlin,有点强买强卖的嫌疑」,这列贴两个官方的图参考一下:
方案二:FormDev(之前推出过 Swing 布局器的开发商,官网 https://www.formdev.com/flatlaf)提供的 FlatLaf(Flat Look and Feel),提供了 Light Dark IntelliJ and Darcula themes,而且依赖少,使用起来十分简单,个人认为当前这个是 Swing UI 组件视觉效果首选
引入 FlatLaf 和 OpenFx 的依赖:
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf-intellij-themes</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11.0.2</version>
</dependency>
布局和实现
=====
布局的实现比较简单:
最终的 H5 文本渲染在 WebView 组件中(JFXPanel 是 JavaFx => Swing 的适配器,WebView 是 JavaFx 的组件,但是这里使用的外层容器都是 Swing 组件),具体的编码实现如下:
public class MarkdownEditor {
private static final int W = 1200;
private static final int H = 1000;
private static final String TITLE = "markdown editor";
public static String CONTENT = "<!DOCTYPE html>\n" +
"<html lang="en">\n" +
"<head>\n" +
" <meta charset="UTF-8"/>\n" +
" <meta name="viewport" content="width=device-width, initial-scale=1.0"/>\n" +
" <title>ByteMD example</title>\n" +
" <link rel="stylesheet" href="https://unpkg.com/bytemd/dist/index.min.css"/>\n" +
" <link rel="stylesheet" href="https://unpkg.com/github-markdown-css"/>\n" +
" <script src="https://unpkg.com/bytemd"></script>\n" +
" <script src="https://unpkg.com/@bytemd/plugin-gfm"></script>\n" +
" <script src="https://unpkg.com/@bytemd/plugin-highlight"></script>\n" +
" <style>\n" +
" .bytemd {\n" +
" height: calc(100vh - 50px);\n" +
" }\n" +
"\n" +
" .footer {\n" +
" width: 100%;\n" +
" height: 30px;\n" +
" left: 0;\n" +
" position: absolute;\n" +
" bottom: 0;\n" +
" text-align: center;\n" +
" }\n" +
" </style>\n" +
"</head>\n" +
"<body>\n" +
"<div class="footer">\n" +
" <a href="https://github.com/bytedance/bytemd">bytemd</a>\n" +
"</div>\n" +
"<script>\n" +
" const plugins = [bytemdPluginGfm(), bytemdPluginHighlight()];\n" +
" const editor = new bytemd.Editor({\n" +
" target: document.body,\n" +
" props: {\n" +
" value: '# heading\n\nparagraph\n\n> blockquote',\n" +
" plugins,\n" +
" },\n" +
" });\n" +
" editor.$on('change', (e) => {\n" +
" editor.$set({value: e.detail.value});\n" +
" });\n" +
"</script>\n" +
"</body>\n" +
"</html>";
static {
// 初始化主题
try {
UIManager.setLookAndFeel(FlatIntelliJLaf.class.getName());
} catch (Exception e) {
throw new IllegalStateException("theme init error", e);
}
}
private static JFrame buildFrame(int w, int h, LayoutManager layoutManager) {
JFrame frame = new JFrame();
frame.setLayout(layoutManager);
frame.setTitle(TITLE);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(w, h);
Toolkit toolkit = Toolkit.getDefaultToolkit();
int x = (int) (toolkit.getScreenSize().getWidth() - frame.getWidth()) / 2;
int y = (int) (toolkit.getScreenSize().getHeight() - frame.getHeight()) / 2;
frame.setLocation(x, y);
return frame;
}
private static void initAndDisplay() {
// 构建窗体
JFrame frame = buildFrame(W, H, new BorderLayout());
JFXPanel panel = new JFXPanel();
评论