代码之家  ›  专栏  ›  技术社区  ›  An SO User

在制作代码编辑器时,JavaFX与JSyntaxPane的等价物是什么?

  •  8
  • An SO User  · 技术社区  · 11 年前

    之前在Swing中,我使用过 JSyntaxPane 用于制作一个小型Java源代码编辑器。为了练习,我决定用JavaFX重做整个项目,并添加对更多语言的支持。最好是尽可能多。

    然而,似乎没有类似的东西 J语法窗格 .

    一点研究让我 Tom Schindl blog 其中他制作了一个具有适当语法高亮显示的源代码查看器。遗憾的是,没有编辑支持。

    然后是 JewelSea blog 但从屏幕截图来看,它看起来像SO type-and-preview 方法在代码编辑器中没有所需的内容。

    再次,来自 JFXperience 我发现在JavaFX8中可以突出显示、缩进和编辑面板/节点,它还允许将Swing嵌入Java中。

    在那之前,我还有什么选择?

    我知道JavaFX可以与JavaScript进行互操作,所以有没有办法使用一些JavaScript库来实现这一点?

    4 回复  |  直到 11 年前
        1
  •  14
  •   Saikat SHASHANK HONRAO    3 年前

    RichTextFX 这可以让你进行高亮显示。查看 Java Keywords example .

    请注意,它需要JDK8。

        2
  •  1
  •   Community CDub    8 年前

    我目前正在使用 Ace Editor 在我的开源项目中通过 WebEngine 。这是 Kitchen Sink 演示。

    更新

    从当前JDK版本开始,JS/FX交互的一种可能方法是:

    • 编写JS应用程序/小部件部分,并对其进行独立测试。如果您只想嵌入一个编辑器小部件,那么它可能是一个带有 <div> 那是你的编辑。
    • 然后,“从JS获取文本”场景的计划可能是这样的:“从Java调用JS函数,它将从编辑器元素获取文本,并用作为方法的String参数传递的文本回调Java部分”。
    • 学习Java JS绑定-即。 WebView callback from Javascript
    • 嵌入FirebugLite,从 WebView 。唯一对我有效的版本是:

      <script src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'>

    一些一般性建议-尽量避免JS到Java调用的复杂性。我向JavaFX团队提交了几个错误,因为一些简单的事情,比如重写一个方法,对我来说不起作用。避免将Java对象传递给JS-尽管理论上这是可能的,但我总是以应用程序崩溃告终。所以现在我正在传递JSON并将其转换为两边的对象。

    你可以 have a look at a working example here AngularJS/JavaFX应用程序。它处于预阿尔法状态,所以它甚至可能不会在你的机器上启动,但可以被视为AngularJS桌面应用程序的概念证明。

        3
  •  1
  •   jewelsea    11 年前

    我发布的编辑器示例不是一个类型和预览方法,而是一个嵌入的JavaScript编辑器( codemirror )使用WebKit将其转换为JavaFX应用程序。你可以找到相关的来源 here 或中的迷你IDE的更新版本 conception project .

        4
  •  0
  •   user1300214 user1300214    4 年前

    adapted this code 对于 RichTextFX 创建我自己包含的TextCodeArea。你应该可以将它添加到你的应用程序中并使用它运行。你只需要将它传递给 AnchorPane 要将自身附加到的节点。

    public class TextCodeArea {
    
        private static final String[] KEYWORDS = new String[] {
                "abstract", "assert", "boolean", "break", "byte",
                "case", "catch", "char", "class", "const",
                "continue", "default", "do", "double", "else",
                "enum", "extends", "final", "finally", "float",
                "for", "goto", "if", "implements", "import",
                "instanceof", "int", "interface", "long", "native",
                "new", "package", "private", "protected", "public",
                "return", "short", "static", "strictfp", "super",
                "switch", "synchronized", "this", "throw", "throws",
                "transient", "try", "void", "volatile", "while"
        };
    
        private static final String KEYWORD_PATTERN = "\\b(" + String.join("|", KEYWORDS) + ")\\b";
        private static final String PAREN_PATTERN = "\\(|\\)";
        private static final String BRACE_PATTERN = "\\{|\\}";
        private static final String BRACKET_PATTERN = "\\[|\\]";
        private static final String SEMICOLON_PATTERN = "\\;";
        private static final String STRING_PATTERN = "\"([^\"\\\\]|\\\\.)*\"";
        private static final String COMMENT_PATTERN = "//[^\n]*" + "|" + "/\\*(.|\\R)*?\\*/";
        private static final String ASSIGNMENT_PATTERN = "\\s+\\w+?\\s+=" + "|" + "\\s+\\w+\\[.*\\]?\\s+=";
    
        private static final Pattern PATTERN = Pattern.compile(
                "(?<KEYWORD>" + KEYWORD_PATTERN + ")"
                        + "|(?<PAREN>" + PAREN_PATTERN + ")"
                        + "|(?<BRACE>" + BRACE_PATTERN + ")"
                        + "|(?<BRACKET>" + BRACKET_PATTERN + ")"
                        + "|(?<SEMICOLON>" + SEMICOLON_PATTERN + ")"
                        + "|(?<STRING>" + STRING_PATTERN + ")"
                        + "|(?<COMMENT>" + COMMENT_PATTERN + ")"
                        + "|(?<ASSIGNMENT>" + ASSIGNMENT_PATTERN + ")"
        );
    
        private CodeArea codeArea;
    
        public  TextCodeArea(AnchorPane pane) {
            codeArea = new CodeArea();
    
            VirtualizedScrollPane sp = new VirtualizedScrollPane(codeArea);
            pane.getChildren().add(sp);
            AnchorPane.setLeftAnchor(sp, 0.0);
            AnchorPane.setRightAnchor(sp, 0.0);
            AnchorPane.setBottomAnchor(sp, 0.0);
            AnchorPane.setTopAnchor(sp, 0.0);
            codeArea.prefWidthProperty().bind(pane.widthProperty());
            codeArea.prefHeightProperty().bind(pane.heightProperty());
            codeArea.setParagraphGraphicFactory(LineNumberFactory.get(codeArea));
            Subscription cleanupWhenNoLongerNeedIt = codeArea.multiPlainChanges()
                    .successionEnds(java.time.Duration.ofMillis(50))
                    .subscribe(ignore -> codeArea.setStyleSpans(0, computeHighlighting(codeArea.getText())));
            final Pattern whiteSpace = Pattern.compile( "^\\s+" );
            codeArea.addEventHandler( KeyEvent.KEY_PRESSED, key -> {
                if (key.getCode() == KeyCode.ENTER) {
                    int pos = codeArea.getCaretPosition();
                    int par = codeArea.getCurrentParagraph();
                    Matcher matcher = whiteSpace.matcher(codeArea.getParagraph(par-1).getSegments().get(0));
                    if (matcher.find()) Platform.runLater(() -> codeArea.insertText(pos, matcher.group()));
                }
            });
    //        cleanupWhenNoLongerNeedIt.unsubscribe();    // to stop and clean up
        }
    
        private static StyleSpans<Collection<String>> computeHighlighting(String text) {
            int lastKwEnd = 0;
            Matcher matcher = PATTERN.matcher(text);
            StyleSpansBuilder<Collection<String>> spansBuilder = new StyleSpansBuilder<>();
    
            while(matcher.find()) {
                String styleClass =
                        matcher.group("KEYWORD") != null ? "keyword" :
                                matcher.group("PAREN") != null ? "paren" :
                                        matcher.group("BRACE") != null ? "brace" :
                                                matcher.group("BRACKET") != null ? "bracket" :
                                                        matcher.group("SEMICOLON") != null ? "semicolon" :
                                                                matcher.group("STRING") != null ? "string" :
                                                                        matcher.group("COMMENT") != null ? "comment" :
                                                                                matcher.group("ASSIGNMENT") != null ? "assignment" :
                                                                                        null; /* never happens */ assert styleClass != null;
                spansBuilder.add(Collections.emptyList(), matcher.start() - lastKwEnd);
                spansBuilder.add(Collections.singleton(styleClass), matcher.end() - matcher.start());
                lastKwEnd = matcher.end();
            }
            spansBuilder.add(Collections.emptyList(), text.length() - lastKwEnd);
            return spansBuilder.create();
        }
    }
    

    还要确保在JavaFX应用程序中包含CSS Main 功能:

        scene.getStylesheets().add(getClass().getResource("../java-keywords.css").toExternalForm());
    
    .styled-text-area {
        -fx-font-size: 18;
        -fx-background-color: rgb(0, 27, 51);
    }
    
    .styled-text-area .caret {
        -fx-stroke: white;
    }
    
    .styled-text-area .text{
        -fx-fill:white;
    }
    
    .styled-text-area .line {
        -fx-fill: black;
    }
    
    .styled-text-area .text.assignment {
        -fx-fill: orange;
        -fx-font-weight: bold;
    }
    
    .styled-text-area .text.keyword {
        -fx-fill: rgb(110, 252, 187);
        -fx-font-weight: bold;
    }
    
    .styled-text-area .text.semicolon {
        -fx-fill: rgb(110, 252, 187);
        -fx-font-weight: bold;
    }
    
    .styled-text-area .text.paren {
        -fx-fill: yellow;
        -fx-font-weight: bold;
    }
    
    .styled-text-area .text.bracket {
        -fx-fill: white;
        -fx-font-weight: bold;
    }
    
    .styled-text-area .text.brace {
        -fx-fill: yellow;
        -fx-font-weight: bold;
    }
    
    .styled-text-area .text.string {
        -fx-fill: rgb(58,213,11);
    }
    
    .styled-text-area .text.comment {
        -fx-fill: rgb(0, 200, 255);
    }
    
    .paragraph-box:has-caret{
        -fx-background-color: rgb(50, 77, 101);
    }