Как я могу сохранить новые символы строки при динамическом создании TextFlow с помощью FXML и JavaFX

Следующий код динамически создает TextFlow и Text, которые изначально содержат новые символы строки (возможно, изображения и другие области).

InputStream stream = new ByteArrayInputStream(text.toString().getBytes(StandardCharsets.UTF_8));
      TextFlow element = new FXMLLoader().load(stream);

Однако метод ByteArrayInputStream с FXML удаляет все новые строки.

Пробовал использовать символы конца строки Windows и Unix, но это не должно иметь значения, но вы доходите до этого момента, когда напрасно пробуете разные комбинации.

Обычно рекомендуется использовать BufferedReader для вернуть новые линии, но здесь я не в контроле. Другие методы загрузки, похоже, принимают URL-адреса и ссылки на ресурсы, однако это управляемая строка.

Пример

Java-код:

package simpleexample;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;

import com.jcabi.xml.XMLDocument;

public class TestFxmlWithBreaks extends Application {


  @Override
  public void start(Stage primaryStage) {
    Scene scene = new Scene(createEntry(), 750, 750, Color.web("#666970"));
    primaryStage.setScene(scene);
    primaryStage.show();

  }


  private VBox createEntry() {
    VBox entryBox = new VBox();
    entryBox.setFillWidth(true);

    entryBox.setSpacing(20);
    entryBox.setMaxWidth(750);

    try {
      XMLDocument test = new XMLDocument(this.getClass().getResourceAsStream("inputFxml.xml"));
      System.out.println(test.toString());

      InputStream stream = new ByteArrayInputStream(test.toString().getBytes(StandardCharsets.UTF_8));
      TextFlow element = new FXMLLoader().load(stream);
      element.setMaxWidth(750);

      entryBox.getChildren().add(element);
    } catch (Exception e) {
      //log something
    }

    return entryBox;
  }


  public static void main(String[] args) {
  launch(args);
  }



}

inputFxml.xml:

<?xml version="1.0" encoding="UTF-8"?><?import javafx.scene.text.*?><TextFlow xmlns:fx="http://javafx.com/fxml" styleClass="paragraph">
<Text style="-fx-font-size: 20;">A list of stuff</Text>
<Text>
* stuff
* more stuff
* even more stuff, all with new lines
</Text>
<Text style="-fx-font-size: 15;">This should demonstrate it</Text>
</TextFlow>

person Daniel Gerson    schedule 06.12.2015    source источник
comment
Можете ли вы показать пример text.toString(), который здесь не работает? т.е. как-нибудь сделать минимально воспроизводимый пример? Трудно понять, что вы пытаетесь сделать... почему бы просто не создать TextFlow с помощью Java вместо FXML и не сгенерировать текстовое содержимое?   -  person James_D    schedule 06.12.2015
comment
Нет проблем, сэр. Я добавил простой пример. XMLDocument здесь, по сути, бесполезен, но на самом деле должны быть XSL-преобразования. Я не могу создать его с помощью java, потому что трансформируется много стороннего контента. Я просто не хочу использовать getResourceAsStream или что-то подобное, если это работает по-другому. println печатает весь документ, как я и ожидал.   -  person Daniel Gerson    schedule 07.12.2015
comment
Ага. Это должно просто работать. Обратите внимание, что это не имеет никакого отношения к потоку: если вы просто загрузите этот файл FXML обычным способом (TextFlow textFlow = FXMLLoader.load(getClass().getResource("inputFxml.fxml"));), вы получите тот же результат. Я посмотрю, смогу ли я найти обходной путь позже.   -  person James_D    schedule 07.12.2015
comment
В конце концов openStream будет вызываться по URL-адресу, поэтому вы можете обнаружить, что это та же проблема, но в другом месте.   -  person Daniel Gerson    schedule 07.12.2015
comment
Обратите внимание, что в этой области есть другие ошибки, и, возможно, этот обходной путь сработает. слишком.   -  person Daniel Gerson    schedule 07.12.2015


Ответы (1)


Поэтому, пока не будет доступно лучшее решение, я выбрал хакерский подход, вставив строку разметки, а затем заменив ее после загрузки fxml.

Не супер, но достаточно для моего варианта использования.

public void markNewLinesInXmlTextNodes(Node node) { //w3c node
    for(int i = 0 ; i < node.getChildNodes().getLength() ; i++) {
      Node child = node.getChildNodes().item(i);
      markNewLinesInXmlTextNodes(child);
    }
    if (node instanceof Element) {
      Element el = (Element) node;
      if (el.getTagName().toLowerCase().equals("text")) {
        el.setTextContent(el.getTextContent().replaceAll("\n", "_LINEBREAK_"));
      }
    }
  }

  public void addNewLinesInFxTextNodes(javafx.scene.Node node) {
    if (node instanceof javafx.scene.Parent) {
      javafx.scene.Parent parent = (javafx.scene.Parent) node;
      for(int i = 0 ; i < parent.getChildrenUnmodifiable().size() ; i++) {
        javafx.scene.Node child = parent.getChildrenUnmodifiable().get(i);
        addNewLinesInFxTextNodes(child);
      }
    }
    if (node instanceof javafx.scene.text.Text) {
      Text el = (Text) node;
      el.setText(el.getText().replaceAll("_LINEBREAK_", "\n"));
    }
  }
person Daniel Gerson    schedule 20.12.2015