我为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 应用程序Main
函数中包含您的 CSS:
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);
}