JavaFx – Abhilfe bei abgeschnittenen Texten

07.06.2018

Durch verschiedene Lauflängen von Texten in unterschiedlichen Sprachen kann es mitunter dazu kommen, dass Texte in JavaFx-Labels abgeschnitten oder mit „…“ abgekürzt werden. Um die Usability von JavaFx Applikationen durch dieses Problem nicht zu verschlechtern, haben wir uns auf die Suche nach einer möglichst generischen Lösung gemacht. Unser Lösungsansatz ist in diesem Beitrag skizziert.

Zum Verständnis der Problemstellung demonstriert der nachfolgende Prototyp das Verhalten.

Zu erkennen ist, dass der längere Text „Noooooooooooooooooooooooooooooooooo“, welcher dargestellt werden soll vorzeitig abgeschnitten und mit „…“ abgekürzt wird, da das Label durch welches er dargestellt wird eine fixe Länge besitzt.

Bei dem Versuch, hier möglichst generisch Abhilfe zu schaffen sind wir zu folgender Lösung gekommen:

  • Bei der Anzeige einer Scene prüfen wir für jeden Node der anzuzeigenden Komponente, ob es sich dabei um eine Instanz von Labeled handelt, um Text-Labels zu erkennen.
  • Wenn dem so ist, kalkulieren wir anhand des Label-Textes mittels Toolkit die Länge des Texts
  • Sobald die Breite des Labels sich verändert (und damit auch beim ersten Mal, wenn die Komponente gezeichnet wird), prüfen wir, ob die kalkulierte Textlänge größer ist, als die Feldlänge des Labels (max- oder prefWidth).
  • Wenn dem so ist, fügen wir dem Label ein Tooltip hinzu, dessen Text durch ein entsprechendes Property Binding an den Text des Labels gebunden ist. Dieses zeigt dann den kompletten Text des Labels an, ohne diesen abzuschneiden. Natürlich sind an dieser Stelle auch andere Anpassungen, wie z.B. die Anpassung der Größe des Labels denkbar.

Im Code lässt sich dies wie folgt abbilden:

   // this method helps solving swallowed texts in labels which are to long for the current
   // layout by adding a tooltip if the labels text overruns the label length.
   private void correctOverfloatingTexts(Parent parent)
   {
      if (parent == null) {
         return;
      }

      for (Node node : parent.getChildrenUnmodifiable()) {

         if (node instanceof Labeled) {

            Labeled labeled = (Labeled)node;

            // add listener to node, because real sizes are not available before node has been
            // painted => when node is painted, width changes from 0/-1 to real width
            labeled.widthProperty().addListener(obs -> {

               // calculate the width of a displayed string
               // https://code.i-harness.com/en/q/c69a92
               double computedWidth = Toolkit.getToolkit().getFontLoader().computeStringWidth(labeled.getText(),
                                                                                              labeled.getFont());
               double prefWidth = labeled.getPrefWidth();
               double maxWidth = labeled.getMaxWidth();

               // compare calculated width to max and pref width and decide whether text is
               // swallowed / overlapping
               boolean swallowedText = false;
               if (maxWidth > 0 && computedWidth > maxWidth && !labeled.isWrapText()) {
                  swallowedText = true;
               }

               if (prefWidth > 0 && computedWidth > prefWidth && !labeled.isWrapText()) {
                  swallowedText = true;
               }

               // if text is swallowed, add a tooltip who's content is bound to the labels text
               // property
               if (swallowedText) {
                  Tooltip tooltip = new Tooltip();
                  tooltip.textProperty().bind(labeled.textProperty());
                  Tooltip.install(labeled, tooltip);
               }

            });

         }

         // if node has children, also check for them (recursive call)
         if (node instanceof Parent) {
            correctOverfloatingTexts((Parent)node);
         }
      }
   }

Das Ergebnis der Anpassung zeigt wiederum unser kleiner Prototyp:

Zwar wird die fixe Länge des Labels beibehalten, der vollständige Text wird aber bei Bedarf durch ein Tooltip angezeigt.

Dadurch kann auf der einen Seite ein fixes Layout eingehalten werden. Auf der anderen Seite gehen für den Benutzer keine Informationen verloren.

Zurück zur Übersicht

2 Kommentare zu “JavaFx – Abhilfe bei abgeschnittenen Texten

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*Pflichtfelder

*