This is the second day of my participation in the August More text Challenge. For details, see:August is more challenging
The premise
One day point to dig gold writing interface, discovered the built-in Markdown editor has a lot of icon, point in bytemd Markdown editor is an open source project (https://github.com/bytedance/bytemd) :
This is a NodeJs project, provided by Bytedance. Remember that there is a component in JavaFx, WebView, which already supports Html5, CSS3 and ES5. This component acts as an embedded browser. You can easily render the text content of a URL or directly render a raw Html string. Also, since native JavaFx is visually ugly, consider introducing Swing with IntelliJ IDEA themes to provide a better look. The code for this article is developed based on JDK11.
Introduction of depend on
Many people have joked that Swing components are visually poor for several reasons:
- Technology niche, now there are better components for hybrid development and cross-platform development
- For this reason, few people develop
Swing
The component’sUI
, in fact,Swing
Can be reimplemented for each component ofUI
Performance effect of compose-jb
(JetBrains
The component was released late and happened toSwing
Official stop maintenance, later should be less people will useSwing
doGUI
The development of
The best known solution that uses Swing and is successful is the JetBrains family bucket. So far, there are simple solutions to this “ugly” problem:
- Option 1: Use
compose-jb
(The name is a bit unpleasant, but the official warehouse ishttps://github.com/JetBrains/compose-jb
) development, this isJetBrains
Series of generic components based onSwing
Do secondary encapsulation,But you have to use languageKotlin
It’s a bit of a bargainHere are two official charts for reference:
- Scheme 2:
FormDev
(It was introduced beforeSwing
Developer of layout, official websitehttps://www.formdev.com/flatlaf
) provided by theFlatLaf
(Flat Look and Feel
), providedLight Dark IntelliJ and Darcula themes
, and less dependence, very simple to use, I think the current one isSwing UI
Component visual effects preferred
Introduce the dependency of FlatLaf and 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>
Copy the code
Layout and Implementation
The implementation of the layout is relatively simple:
The final H5 text is rendered in the WebView component (JFXPanel is a JavaFx => Swing adapter, WebView is a JavaFx component, but the outer container used here is all Swing components). The encoding implementation is as follows:
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 = "
\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
"
\n" +
"
\n" +
" ByteMD example \n" +
"
\n" +
"
\n" +
" \n" +
" \n" +
" \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" +
" \n" +
"</head>\n" +
"<body>\n" +
"<div class=\"footer\">\n" +
" bytemd\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 {
// Initialize the theme
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(a) {
// Build the form
JFrame frame = buildFrame(W, H, new BorderLayout());
JFXPanel panel = new JFXPanel();
Platform.runLater(() -> {
panel.setSize(W, H);
initWebView(panel, CONTENT);
frame.getContentPane().add(panel);
});
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(MarkdownEditor::initAndDisplay);
}
private static void initWebView(JFXPanel fxPanel, String content) {
StackPane root = new StackPane();
Scene scene = new Scene(root);
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.setJavaScriptEnabled(true); webEngine.loadContent(content); root.getChildren().add(webView); fxPanel.setScene(scene); }}Copy the code
H5 text from byTEMd native JS implementation example:
All the code is about 120 lines plus comments. Run with JDK11, the result is as follows:
There are currently 2 unresolved issues (or possible ones) :
JS
There was a slight delay in triggering the actionWebView
Component initialization is slow
summary
The Oracle JDK has officially announced that the Swing project will no longer be maintained and is likely to be removed from the JDK as usual, perhaps because it does not represent its own value (low emotional intelligence: it does not make money). The layout of Swing development is anti-human. The layout of a Swing project may take more than 90% of the time. The UI design of native components is “ugly”, there are no rich extensions and active communities. Add to that the fact that there are better cross-platform development options out there such as Qt, React Native, Flutter, etc., and Swing’s oblivion is a foregone conclusion. With the exception of JetBrains, Swing ended up as a minority business hobby and a collection of JDK GUI programming enthusiasts.
The Demo source code:
- local-markdown-editor(
https://gitee.com/throwableDoge/local-markdown-editor
)
(E-A-20210815 C-1-D)