Cet article est le 14ème jour du Calendrier de l'Avent JavaFX 2016. Hier, c'était "Définir l'icône native avec javafx-maven-plugin" de @ sk44_. Demain, ce sont les "Notes sur l'appel de l'API Payara Micro depuis JavaFX" de @ khasunuma.
Lors de l'implémentation d'un éditeur dans JavaFX, vous êtes-vous déjà senti insatisfait de l'expressivité et des subtilités de TextArea standard?
Dans cet article, je vais vous présenter la bibliothèque "RichTextFX" que je voudrais recommander à ceux qui veulent faire des outils avec fonction éditeur avec JavaFX ou qui l'ont fait.
Une bibliothèque développée par Tomas Mikula qui fournit des composants d'édition de texte riche. Vous pouvez trouver le code de démonstration et son utilisation dans le référentiel GitHub.
Licence BSD à 2 clauses et licence double d'exception de chemin de classe GPLv2.
JDK 8 ou supérieur, car il utilise javafx.scene.text.TextFlow Est requis.
L'environnement utilisé dans cette introduction est le suivant.
Java SE | 1.8.0_102 |
---|---|
OS | Windows 10 |
Gradle | 3.0 |
Utilisez FizzBuzz de Groovy comme un code très simple.
FizzBuzz.groovy
(1..100)
.collect{it % 15 == 0 ? "FizzBuzz" : it % 3 ==0 ? "Fizz" : it % 5 == 0 ? "Buzz" : it}
.forEach{print it + ", "}
Ajoutez la ligne suivante aux dépendances.
build.gradle
dependencies {
+ compile 'org.fxmisc.richtext:richtextfx:0.7-M2'
......
}
Il est implémenté comme une entité complètement distincte du TextArea standard et n'est pas compatible. Faites attention.
<?import org.fxmisc.richtext.CodeArea?>
Veuillez noter que l'info-bulle ne peut pas être utilisée.
- <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" />
La classe Controller doit également être modifiée.
-import javafx.scene.control.TextArea;
+import org.fxmisc.richtext.CodeArea;
TextArea et CodeArea ne sont pas compatibles et doivent être remplacés.
@FXML
- public TextArea scripterInput;
+ public CodeArea scripterInput;
@FXML
- public TextArea scripterOutput;
+ public CodeArea scripterOutput;
Veuillez noter que les noms des méthodes sont également différents.
- scripterOutput.setText(result);
+ scripterOutput.replaceText(result);
Dans son état d'origine, il n'y a pas de mise en surbrillance du code, pas d'affichage du numéro de ligne et pas de retour à la ligne.
Ensuite, affichons le numéro de ligne.
+import org.fxmisc.richtext.LineNumberFactory;
Pour chaque objet CodeArea, spécifiez ParagraphGraphicFactory comme indiqué ci-dessous.
Définir l'affichage du numéro de ligne avec setParagraphGraphicFactory
scripterOutput.setParagraphGraphicFactory(LineNumberFactory.get(scripterInput));
De cette manière, le numéro de ligne est affiché.
Si vous essayez de couper la ligne, le nombre de lignes s'affiche autant que le saut de ligne.
S'il dépasse 100 lignes, il s'affichera correctement sur 3 chiffres.
CodeArea nécessite une petite implémentation, mais il peut être mis en évidence avec un format / mot-clé spécifique. Une fonctionnalité de cette bibliothèque est la mise en évidence asynchrone. Vous pouvez mettre en évidence vos modifications en temps réel. L'implémentation utilise ReactFX, une bibliothèque de Reactive Streams développée par le même Tomas Mikula.
Un exemple d'implémentation dans le langage de programmation Java est fourni ci-dessous.
https://github.com/TomasMikula/RichTextFX/blob/master/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/JavaKeywordsAsync.java
Cette fois, implémentons un exemple dans Groovy.
Il semble qu'il y ait 57 types ci-dessous. Si vous êtes un expert, veuillez le signaler si vous faites une erreur.
Groovy's 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
Enregistrez-le dans un fichier texte.
Cette fois, [Échantillon officiel](https://github.com/TomasMikula/RichTextFX/blob/2b4ba4378cfe27facfd86051771946ed9c0dc691/richtextfx-demos/src/main/resources/org/fxmisc/rich/demo est utilisé comme mot-clé). Je vais l'utiliser.
CSS pour les mots-clés
.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;
}
Vous pouvez placer ce fichier CSS n'importe où, mais cette fois, c'est juste sous src / main / resources.
Tout d'abord, définissez une classe qui possède des méthodes couramment utilisées pour mettre en évidence les implémentations. Élevé à partir du code de démonstration JavaKeywordsAsync.java Extrayez uniquement la pièce à traiter et définissez uniquement le traitement commun en tant que classe abstraite.
https://github.com/toastkidjp/javafx_advent2015/blob/v2016/src/main/java/jp/toastkid/highlight/Highlight.java
Une méthode qui exécute un traitement asynchrone. Appelez cette méthode depuis votre application.
Héritez de la classe Highlight ci-dessus pour créer une classe qui met en évidence la syntaxe de Groovy.
https://github.com/toastkidjp/javafx_advent2015/blob/v2016/src/main/java/jp/toastkid/highlight/GroovyHighlight.java
Cette méthode lit les mots-clés à partir du fichier de mots-clés préparé précédemment et crée une expression régulière pour la mise en évidence du code. Les expressions régulières autres que les mots-clés sont prédéfinies. Vous pouvez créer une classe Highlight pour chaque langue en modifiant les éléments suivants pour chaque langue.
Expression régulière pour la mise en évidence du code
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)*?\\*/";
Une méthode qui prend le texte de CodeArea et le convertit dans un format qui permet la mise en évidence du code.
Ajoutez ce qui suit à la dernière ligne de la méthode initialize.
initialize()
new GroovyHighlight(scripterInput).highlight();
En outre, ajoutez l'URI du fichier CSS pour la coloration des mots clés que vous avez préparée précédemment aux feuilles de style de l'objet Scene.
src/main/Directement sous les ressources"keywords.css"Vers les feuilles de style
final ObservableList<String> stylesheets = thisStage.getScene().getStylesheets();
stylesheets.add(getClass().getClassLoader().getResource("keywords.css").toExternalForm());
Ceci termine la préparation.
Essayez de saisir le code FizzBuzz ci-dessous.
FizzBuzz
int i = 0
(1..100)
.collect{it % 15 == 0
? "FizzBuzz"
: it % 3 ==0
? "Fizz"
: it % 5 == 0
? "Buzz"
: it
}
.forEach{print it + ", "}
Comme vous pouvez le voir, int est rougeâtre, les commentaires sont vert clair et les chaînes littérales entre "sont bleues.
Pour d'autres exemples d'implémentation simples de points forts du code, veuillez consulter le référentiel ci-dessous si vous êtes intéressé (l'application elle-même n'est pas incluse).
https://github.com/toastkidjp/simple_highlight
J'ai recommandé RichTextFX jusqu'à présent, mais j'ai écrit cet article avant de l'intégrer dans l'application réelle, et plus tard j'ai remarqué un bogue qui ne peut pas être négligé, je vais donc l'ajouter.
Jetez d'abord un œil à l'image ci-dessous. Une fenêtre avec trois zones de texte alignées s'affiche, et les candidats à la conversion sont affichés en entrant «à côté de» dans la zone de texte à gauche (CodeArea de RichTextFX).
Avez-vous ressenti un inconfort? Oui, le texte saisi et les candidats à la conversion sont affichés dans le coin supérieur gauche de l'écran. C'est un état assez stupide ... C'est la classe de contrôle de texte de RichTextFX [javafx.scene.control.TextInputControl](https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/ Il semble que la cause soit que control / TextInputControl.html) n'est pas implémenté. ~~ Je me demande si l'auteur n'a pas eu besoin de saisir des caractères multi-octets …… ~~
Bien sûr, ce n'était pas le cas, et la personne qui a signalé et proposé des mesures d'amélioration a créé le problème.
How to insert text using an Input Method #146
En regardant le problème ci-dessus, il a été dit que "j'ai implémenté InputMethodRequests et je l'ai résolu", j'ai donc pensé essayer s'il pouvait être amélioré, et j'ai implémenté ceci [EditorInputMethodRequests](https: // github. com / toastkidjp / RichTextFX_verification / blob / verification / src / main / java / jp / toastkid / rtfx_verification / EditorInputMethodRequests.java). Il était assez facile à mettre en œuvre en utilisant la méthode getCaretBounds () ajoutée dans SNAPSHOT 1.0.0.
codeArea.setInputMethodRequests(new EditorInputMethodRequests(improved));
Eh bien, plutôt que cela, implémentez le contenu de setOnInputMethodTextChanged C'était plus difficile, mais ...
codeArea.setOnInputMethodTextChanged(this::handleInputMethodEvent);
La zone de texte centrale est l'endroit où ces correctifs sont appliqués. Cette
Le texte d'entrée s'affiche correctement à la position du report et les candidats à la conversion sont également affichés en dessous. Enfin, c'est à un niveau qui peut être utilisé comme un éditeur minimum.
Je pensais que ce n'était pas le cas.
La zone de texte sur la droite est le TextArea standard JavaFX. La partie incertaine du texte d'entrée est soulignée et la plage des candidats à la conversion est mise en évidence avec un arrière-plan bleu. Il est difficile de le mettre en pratique s'il n'atteint pas ce niveau, mais nous n'avons pas été en mesure de mettre en œuvre les fonctions jusqu'à présent. Si vous êtes intéressé, il peut être intéressant de l'essayer en vous référant au code des 3 classes suivantes.
Pour utiliser RichTextFX 1.0.0-SNAPSHOT à partir du 6 février 2017, ajoutez `` https: // oss.sonatype.org / content / repositories / snapshots / '' dans les référentiels de build.gradle. Il est nécessaire d'ajouter la spécification du référentiel de.
build.gradle
repositories {
mavenCentral()
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
https://github.com/toastkidjp/RichTextFX_verification/tree/verification
Selon l'article de @ nodamushi "JavaFX 9 s'améliore" du JavaFX Advent Calendar 2016, JavaFX 9 Il semble qu'il soit possible d'implémenter TextArea qui ne peut afficher les numéros de ligne qu'avec l'API standard. Les attentes augmentent.
Nous venons de présenter brièvement RichTextFX, une bibliothèque qui vous aide à implémenter des fonctionnalités d'édition de texte enrichi dans JavaFX. Le référentiel officiel contient divers codes de démonstration qui n'ont pas pu être introduits cette fois, tels que l'éditeur XML et le redimensionnement des polices. Si vous développez un éditeur Markdown ou HTML, ou si vous souhaitez insérer un exemple de code dans un outil de présentation développé avec JavaFX, vous pouvez envisager d'introduire cette bibliothèque.
RichTextFX CSS Reference Guide https://github.com/TomasMikula/RichTextFX/wiki/RichTextFX-CSS-Reference-Guide