{"id":2372,"date":"2014-01-06T08:58:20","date_gmt":"2014-01-06T07:58:20","guid":{"rendered":"http:\/\/sahits.ch\/blog\/?p=2372"},"modified":"2014-01-06T08:58:20","modified_gmt":"2014-01-06T07:58:20","slug":"textflow-with-javafx-2","status":"publish","type":"post","link":"http:\/\/sahits.ch\/blog\/blog\/2014\/01\/06\/textflow-with-javafx-2\/","title":{"rendered":"TextFlow with JavaFX 2"},"content":{"rendered":"<p>When ever you want to display a large portion of text in your application the <a href=\"http:\/\/docs.oracle.com\/javafx\/2\/api\/javafx\/scene\/text\/Text.html\">Text<\/a> node is your friend. Text allows you to define a wrapping width and thereby allows nice multyline text without letting you bother about the line break.<\/p>\n<p>However what when your text is not that simple? It might contain portions that are differently formatted? Links? Or even icons?<\/p>\n<p>JavaFX 8 has a solution for this: <a href=\"http:\/\/download.java.net\/jdk8\/jfxdocs\/javafx\/scene\/text\/TextFlow.html\">TextFlow<\/a>. If you are however stuck with JavaFX 2 for whatever reason, there is simple workaround: pack all the Nodes into a FlowPane and define the wrapping width to be the preferred width.<\/p>\n<pre class=\"brush:javafx\">public class DecoratedText extends FlowPane {\r\n\r\n    private IntegerProperty wrappingWidth;\r\n    private ReadOnlyObjectProperty&lt;Font&gt; font;\r\n    public DecoratedText(Font font) {\r\n        super(Orientation.HORIZONTAL);\r\n        wrappingWidth = new SimpleIntegerProperty(this, \"wrappingWidth\", 0);\r\n        getStylesheets().add(getClass().getResource(getClass().getSimpleName()+\".css\").toExternalForm());\r\n        this.font = new SimpleObjectProperty&lt;&gt;(this, \"font\", font);\r\n        prefWidthProperty().bindBidirectional(wrappingWidth);\r\n    }\r\n\r\n    \/**\r\n     * Append text. If the text represents a paragraph (indicated by '\\n'), it\r\n     * is not broken up into its parts.\r\n     * @param text\r\n     *\/\r\n    public void append(String text) {\r\n        if (text.endsWith(\"\\n\")) {\r\n            Text decoText = new Text(text);\r\n            \/\/decoText.getStyleClass().add(\"decoratedText-text\");\r\n            decoText.setFont(font.get());\r\n            decoText.wrappingWidthProperty().bind(wrappingWidth);\r\n            getChildren().add(decoText);\r\n        } else {\r\n            String[] parts = text.split(\" \");\r\n            for (String part : parts) {\r\n                Text decoText = new Text(part+\" \");\r\n                \/\/decoText.getStyleClass().add(\"decoratedText-text\");\r\n                decoText.setFont(font.get());\r\n                getChildren().add(decoText);\r\n            }\r\n        }\r\n    }\r\n\r\n    \/**\r\n     * Append a control.\r\n     * @param control\r\n     *\/\r\n    public void append(Node control) {\r\n         getChildren().add(control);\r\n    }\r\n\r\n    public int getWrappingWidth() {\r\n        return wrappingWidth.get();\r\n    }\r\n\r\n    public IntegerProperty wrappingWidthProperty() {\r\n        return wrappingWidth;\r\n    }\r\n\r\n    public void setWrappingWidth(int wrappingWidth) {\r\n        this.wrappingWidth.set(wrappingWidth);\r\n    }\r\n}<\/pre>\n<p>The idea here is to leave text blocks which represent a paragraph by themselves as Text node. However if the paragraph contains some other node, it is splitt up into words. Thereby delegating the wrapping functionality to the underlying FlowPane.<\/p>\n<p>While this solution here is not particularly sophisticated, it suffices my needs. Nevertheless I will replace it with TextFlow as soon as I migrate to Java 8.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When ever you want to display a large portion of text in your application the Text node is your friend. Text allows you to define a wrapping width and thereby allows nice multyline text without letting you bother about the line break. However what when your text is not that simple? It might contain portions &hellip; <a href=\"http:\/\/sahits.ch\/blog\/blog\/2014\/01\/06\/textflow-with-javafx-2\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eTextFlow with JavaFX 2\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[252],"class_list":["post-2372","post","type-post","status-publish","format-standard","hentry","category-java","tag-javafx"],"_links":{"self":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/2372","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/comments?post=2372"}],"version-history":[{"count":1,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/2372\/revisions"}],"predecessor-version":[{"id":2373,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/2372\/revisions\/2373"}],"wp:attachment":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/media?parent=2372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/categories?post=2372"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/tags?post=2372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}