[JAVA] Implementieren Sie Rich-Text-Bearbeitungsfunktionen mit RichTextFX

Dieser Artikel ist der 14. Tag von JavaFX Adventskalender 2016. Gestern war @ sk44_s "Natives Symbol mit javafx-maven-plugin festlegen". Morgen ist @ khasunumas "Hinweise zum Aufrufen der Payara Micro API von JavaFX".

Überblick

Haben Sie sich bei der Implementierung eines Editors in JavaFX jemals mit der Ausdruckskraft und den Feinheiten der Standard-TextArea unzufrieden gefühlt?

In diesem Artikel stelle ich die Bibliothek "RichTextFX" vor, die ich all jenen empfehlen möchte, die Tools mit Editorfunktion mit JavaFX erstellen möchten oder diese erstellt haben.


Was ist RichTextFX?

Eine von Tomas Mikula entwickelte Bibliothek, die Rich-Text-Bearbeitungskomponenten bereitstellt. Sie finden den Demo-Code und die Verwendung im GitHub-Repository.

Lizenz

BSD 2-Klausel-Lizenz und GPLv2-Klassenpfadausnahme-Doppellizenz.

Bedarf

JDK 8 oder höher, weil es [javafx.scene.text.TextFlow] verwendet (https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/text/TextFlow.html) Wird benötigt.

Was Sie mit RichTextFX tun können

  1. Zeilennummernanzeige
  2. Syntax-Highlights
  3. Ändern Sie die Schriftart

Zuerst vorstellen

Umgebung

Die in dieser Einführung verwendete Umgebung ist wie folgt.

Java SE 1.8.0_102
OS Windows 10
Gradle 3.0

Testcode

Verwenden Sie Groovys FizzBuzz als sehr einfachen Code.

FizzBuzz.groovy


(1..100)
  .collect{it % 15 == 0 ? "FizzBuzz" :  it % 3 ==0 ? "Fizz" : it % 5 == 0 ? "Buzz" : it}
  .forEach{print it + ", "}

Vor der Korrektur

ss2016_1.png

Zuerst ersetzen

Gradle-Abhängigkeit hinzugefügt

Fügen Sie Abhängigkeiten die folgende Zeile hinzu.

build.gradle


dependencies {
+  compile 'org.fxmisc.richtext:richtextfx:0.7-M2'
......
}

FXML-Änderung

Es wird als völlig separate Einheit von der Standard-TextArea implementiert und ist nicht kompatibel. Achtung.

Import hinzufügen

<?import org.fxmisc.richtext.CodeArea?>

Ersetzen Sie das TextArea-Tag durch CodeArea

Bitte beachten Sie, dass der Tooltip nicht verwendet werden kann.

-        <TextArea fx:id="scripterInput" prefHeight="550.0" prefWidth="500.0">
-          <tooltip><Tooltip text="input script." /></tooltip>
-        </TextArea>
+        <CodeArea fx:id="scripterInput" prefHeight="550.0" prefWidth="500.0" />

Änderung des Quellcodes

Die Controller-Klasse muss ebenfalls geändert werden.

Import korrigieren

-import javafx.scene.control.TextArea;
+import org.fxmisc.richtext.CodeArea;

Ersetzen Sie TextArea durch CodeArea

TextArea und CodeArea sind nicht kompatibel und müssen ersetzt werden.

     @FXML
-    public TextArea scripterInput;
+    public CodeArea scripterInput;

     @FXML
-    public TextArea scripterOutput;
+    public CodeArea scripterOutput;

Ändern Sie setText in replaceText

Bitte beachten Sie, dass auch die Methodennamen unterschiedlich sind.

-        scripterOutput.setText(result);
+        scripterOutput.replaceText(result);

Modifizierter Screenshot

Im ursprünglichen Zustand gibt es keine Code-Hervorhebung, keine Zeilennummernanzeige und keinen Umbruch.

ss2016_2.png


Zeilennummer anzeigen

Als nächstes zeigen wir die Zeilennummer an.

Import hinzufügen

+import org.fxmisc.richtext.LineNumberFactory;

Angeben von ParagraphGraphicFactory

Geben Sie für jedes CodeArea-Objekt ParagraphGraphicFactory an, wie unten gezeigt.

Stellen Sie die Zeilennummernanzeige mit setParagraphGraphicFactory ein


scripterOutput.setParagraphGraphicFactory(LineNumberFactory.get(scripterInput));

Modifizierter Screenshot

rtfx1.png

Auf diese Weise wird die Zeilennummer angezeigt.

rtfx2.png

Wenn Sie versuchen, den Zeilenumbruch zu unterbrechen, wird die Anzahl der Zeilen genauso angezeigt wie der Zeilenumbruch.

rtfx3.png

Wenn mehr als 100 Zeilen vorhanden sind, wird es dreistellig angezeigt.


Code-Highlights

CodeArea erfordert eine kleine Implementierung, kann jedoch mit einem bestimmten Format / Schlüsselwort hervorgehoben werden. Eine Funktion dieser Bibliothek ist die asynchrone Hervorhebung. Sie können Ihre Änderungen in Echtzeit hervorheben. Die Implementierung verwendet ReactFX, eine Bibliothek reaktiver Streams, die von demselben Tomas Mikula entwickelt wurde.

Eine Beispielimplementierung in der Programmiersprache Java finden Sie unten.

https://github.com/TomasMikula/RichTextFX/blob/master/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/JavaKeywordsAsync.java

Implementierte Groovy-Code-Highlights

Lassen Sie uns dieses Mal ein Beispiel in Groovy implementieren.

Erstellen Sie eine Liste mit Groovy-Schlüsselwörtern

Es scheint, dass es unten 57 Typen gibt. Wenn Sie ein Experte sind, weisen Sie bitte darauf hin, wenn Sie einen Fehler machen.

Groovy's&nbsp;keywords


abstract
as
assert
boolean
break
byte
case
catch
char
class
const
continue
def
default
do
double
else
enum
extends
false
final
finally
float
for
goto
if
implements
import
in
instanceof
int
interface
long
native
new
null
package
private
protected
public
return
short
static
strictfp
super
switch
synchronized
this
threadsafe
throw
throws
transient
true
try
void
volatile
while

Speichern Sie dies in einer Textdatei.

Bereiten Sie die CSS-Datei für die Keyword-Färbung vor

Diesmal ist [Offizielles Beispiel](https://github.com/TomasMikula/RichTextFX/blob/2b4ba4378cfe27facfd86051771946ed9c0dc691/richtextfx-demos/src/main/resources/org/fxmisc/richtext/demo verwendet). Ich werde es benutzen.

CSS für Schlüsselwörter


.keyword {
    -fx-fill: purple;
    -fx-font-weight: bold;
}
.semicolon {
    -fx-font-weight: bold;
}
.paren {
    -fx-fill: firebrick;
    -fx-font-weight: bold;
}
.bracket {
    -fx-fill: darkgreen;
    -fx-font-weight: bold;
}
.brace {
    -fx-fill: teal;
    -fx-font-weight: bold;
}
.string {
    -fx-fill: blue;
}

.comment {
    -fx-fill: cadetblue;
}

.paragraph-box:has-caret {
    -fx-background-color: #f2f9fc;
}

Sie können diese CSS-Datei überall ablegen, diesmal jedoch direkt unter src / main / resources.

Definieren Sie die Basis-Highlight-Klasse

Definieren Sie zunächst eine Klasse mit Methoden, die häufig zum Hervorheben von Implementierungen verwendet werden. Hoch vom Demo-Code JavaKeywordsAsync.java Extrahieren Sie nur den zu verarbeitenden Teil und definieren Sie nur die allgemeine Verarbeitung als abstrakte Klasse.

Implementierungsbeispiel: Highlight.java

https://github.com/toastkidjp/javafx_advent2015/blob/v2016/src/main/java/jp/toastkid/highlight/Highlight.java

Methode hervorheben

Eine Methode, die die asynchrone Verarbeitung ausführt. Rufen Sie diese Methode in Ihrer Anwendung auf.

Groovy Individuelle Highlight-Klasse erstellen

Erben Sie die obige Highlight-Klasse, um eine Klasse zu erstellen, die die Syntax von Groovy hervorhebt.

Implementierungsbeispiel: GroovyHighlight.java

https://github.com/toastkidjp/javafx_advent2015/blob/v2016/src/main/java/jp/toastkid/highlight/GroovyHighlight.java

makePattern-Methode

Diese Methode liest Schlüsselwörter aus der zuvor erstellten Schlüsselwortdatei und erstellt einen regulären Ausdruck für die Codehervorhebung. Andere reguläre Ausdrücke als Schlüsselwörter sind vordefiniert. Sie können eine Highlight-Klasse für jede Sprache erstellen, indem Sie für jede Sprache Folgendes ändern.

Regulärer Ausdruck für die Code-Hervorhebung


    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)*?\\*/";
computeHighlighting-Methode

Eine Methode, die den Text von CodeArea in ein Format konvertiert, das das Hervorheben von Code ermöglicht.

Hinzufügen der Verarbeitung zur Controller-Klasse

Fügen Sie der letzten Zeile der Initialisierungsmethode Folgendes hinzu.

initialize()


new GroovyHighlight(scripterInput).highlight();

Fügen Sie außerdem den URI der CSS-Datei für die zuvor vorbereitete Keyword-Färbung zu den Stylesheets des Scene-Objekts hinzu.

src/main/Direkt unter Ressourcen"keywords.css"Zu Stylesheets


final ObservableList<String> stylesheets = thisStage.getScene().getStylesheets();
stylesheets.add(getClass().getClassLoader().getResource("keywords.css").toExternalForm());

Damit ist die Vorbereitung abgeschlossen.

Modifizierter Screenshot

Geben Sie unten den FizzBuzz-Code ein.

FizzBuzz


int i = 0

(1..100)
  .collect{it % 15 == 0 
    ? "FizzBuzz" 
    : it % 3 ==0 
      ? "Fizz" 
      : it % 5 == 0 
        ? "Buzz" 
        : it
  }
  .forEach{print it + ", "}

rtfx4.png

Wie Sie sehen können, ist int rötlich, Kommentare sind hellgrün und Zeichenfolgenliterale in "sind blau".

Implementierungsbeispiel

Weitere einfache Implementierungsbeispiele für Code-Highlights finden Sie im folgenden Repository, wenn Sie interessiert sind (die Anwendung selbst ist nicht enthalten).

https://github.com/toastkidjp/simple_highlight


(Ergänzung) Über das Problem der japanischen Eingabe

Ich habe RichTextFX bisher empfohlen, aber ich habe diesen Artikel geschrieben, bevor ich ihn in die eigentliche Anwendung eingebettet habe. Später habe ich einen Fehler festgestellt, der nicht übersehen werden kann. Deshalb werde ich ihn hinzufügen.

Was ist los?

Schauen Sie sich zunächst das Bild unten an. Ein Fenster mit drei aneinandergereihten Textbereichen wird angezeigt, und Conversion-Kandidaten werden angezeigt, indem Sie im Textbereich links "neben" eingeben (CodeArea von RichTextFX).

rtfx1.png

Haben Sie sich unwohl gefühlt? Ja, der eingegebene Text und die Conversion-Kandidaten werden oben links auf dem Bildschirm angezeigt. Es ist ein ziemlich dummer Zustand ... Dies ist die Textsteuerungsklasse von RichTextFX javafx.scene.control.TextInputControl. Es scheint, dass die Ursache darin besteht, dass control / TextInputControl.html) nicht implementiert ist. ~~ Ich frage mich, ob der Autor keine Mehrbyte-Zeichen eingeben musste …… ~~

Hat es sonst niemand lustig gefunden?

Dies war natürlich nicht der Fall, und die Person, die auf Verbesserungsmaßnahmen hinwies und diese vorschlug, schuf das Problem.

How to insert text using an Input Method #146

Implementieren Sie InputMethodRequests

Mit Blick auf das obige Problem wurde gesagt, dass "ich InputMethodRequests implementiert und gelöst habe", also dachte ich, ich würde versuchen, es zu verbessern, und ich implementierte es hier [EditorInputMethodRequests](https: // github. com / toastkidjp / RichTextFX_verification / blob / verification / src / main / java / jp / toastkid / rtfx_verification / EditorInputMethodRequests.java). Die Implementierung mit der in SNAPSHOT 1.0.0 hinzugefügten Methode getCaretBounds () war recht einfach.

codeArea.setInputMethodRequests(new EditorInputMethodRequests(improved));

Implementieren Sie stattdessen Inhalt von setOnInputMethodTextChanged Es war schwieriger, aber ...

codeArea.setOnInputMethodTextChanged(this::handleInputMethodEvent);

Nach der Verbesserung

Im zentralen Textbereich werden diese Korrekturen angewendet. Dies

rtfx2.png

Der Eingabetext wird an der Position des Übertrags korrekt angezeigt, und Konvertierungskandidaten werden auch darunter angezeigt. Endlich ist es auf einer Ebene, die als Mindesteditor verwendet werden kann.

Tage der unendlichen Verbesserung

Ich dachte das wäre nicht der Fall.

rtfx4.png

Der Textbereich rechts ist der JavaFX-Standard TextArea. Der unsichere Teil des Eingabetextes ist unterstrichen und der Bereich der Konvertierungskandidaten wird mit einem blauen Hintergrund hervorgehoben. Es ist schwierig, es in die Praxis umzusetzen, wenn es dieses Niveau nicht erreicht, aber wir konnten die Funktionen bisher nicht implementieren. Wenn Sie interessiert sind, kann es interessant sein, es anhand des Codes der folgenden 3 Klassen zu versuchen.

  1. TextInputControlSkin
  2. TextFieldSkin
  3. TextAreaSkin

1.0.0-Hinweise zur Verwendung von SNAPSHOT

Um RichTextFX 1.0.0-SNAPSHOT ab dem 6. Februar 2017 zu verwenden, fügen Sie `https: // oss.sonatype.org / content / repositories / snapshots /` in die Repositorys von build.gradle ein. Es ist erforderlich, die Repository-Spezifikation von hinzuzufügen.

build.gradle


repositories {
    mavenCentral()
    maven {
        url 'https://oss.sonatype.org/content/repositories/snapshots/'
    }
}

Beispiel für ein Anwendungsrepository (GitHub)

https://github.com/toastkidjp/RichTextFX_verification/tree/verification


JavaFX 9 oder höher

Laut @ nodamushis Artikel "JavaFX 9 wird besser" des JavaFX-Adventskalenders 2016, JavaFX 9 Es scheint möglich zu sein, TextArea zu implementieren, das Zeilennummern nur mit der Standard-API anzeigen kann. Die Erwartungen steigen.


Zusammenfassung

Wir haben gerade kurz RichTextFX vorgestellt, eine Bibliothek, mit der Sie Rich-Text-Bearbeitungsfunktionen in JavaFX implementieren können. Das offizielle Repository enthält verschiedene Demo-Codes, die diesmal nicht eingeführt werden konnten, z. B. den XML-Editor und die Größenänderung von Schriftarten. Wenn Sie einen Markdown-Editor oder einen HTML-Editor entwickeln oder Beispielcode in ein in JavaFX entwickeltes Präsentationstool einfügen möchten, sollten Sie diese Bibliothek einführen.


Referenz

RichTextFX CSS Reference Guide https://github.com/TomasMikula/RichTextFX/wiki/RichTextFX-CSS-Reference-Guide

Dieser Quellcode

Recommended Posts

Implementieren Sie Rich-Text-Bearbeitungsfunktionen mit RichTextFX
Implementieren Sie einen Textlink mit Springboot + Thymeleaf