How to load FXML from string in JavaFX


Question

I am new to JavaFX, and I tried search solution for this problem in stackoverflow and google, but could not find a solution.

Sorry, if this is a reporst.

Here is my question. I am trying to load FXML from a string, is this possible? Let's say string result contains the FXML information.

InputStream IS2 = new ByteArrayInputStream(result.getBytes("UTF-8"));

FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());

Parent root = (Parent) fxmlLoader.load(IS2);  

But the code wont work.

Thanks for all your help.

1
3
5/14/2013 5:06:06 PM

Loading FXML from a String works for me (Java 8b89, OS X 10.8)

FXMLLoader loader = new FXMLLoader();
AnchorPane layout = (AnchorPane) loader.load(
  new ByteArrayInputStream(FXML_STRING.getBytes())
);

Note that relative references won't work. For example, in the sample code below, css stylesheet inclusion is commented out as it requires a full url rather than just a relative filename to resolve (as there is no relative path to resolve against when loading from an InputStream).

Here is an adaption of an FXML sample to load the FXML from a string rather than a file:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

import java.io.ByteArrayInputStream;
import java.io.IOException;

/** Main application class for fruit combo fxml demo application */
public class FruitComboStringApplication extends Application {
  public static void main(String[] args) { launch(args); }
  @Override public void start(Stage stage) throws IOException {
    stage.setTitle("Choices");
    stage.getIcons().add(new Image("http://files.softicons.com/download/application-icons/pixelophilia-icons-by-omercetin/png/32/apple-green.png"));
    FXMLLoader loader = new FXMLLoader();
    AnchorPane layout = (AnchorPane) loader.load(new ByteArrayInputStream(FXML.getBytes()));
// alternate code to load from a file rather than a String:
//    AnchorPane layout = FXMLLoader.load(
//      new URL(FruitComboStringApplication.class.getResource("fruitcombo.fxml").toExternalForm())
//    );
    stage.setScene(new Scene(layout));
    stage.show();
  }

  private static final String FXML =
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
      "\n" +
      "<!-- fruitcombo.fxml\n" +
      "     place in same directory as FruitComboApplication.java\n" +
      "     ensure build system copies the fxml file to the build output path -->\n" +
      "<?import java.lang.*?>\n" +
      "<?import java.net.*?>\n" +
      "<?import java.util.*?>\n" +
      "<?import javafx.collections.*?>\n" +
      "<?import javafx.scene.control.*?>\n" +
      "<?import javafx.scene.image.*?>\n" +
      "<?import javafx.scene.layout.*?>\n" +
      "<?import javafx.scene.paint.*?>\n" +
      "<?scenebuilder-stylesheet fruitcombo.css?>\n" +
      "\n" +
      "<AnchorPane maxHeight=\"-Infinity\" maxWidth=\"-Infinity\" minHeight=\"-Infinity\" minWidth=\"-Infinity\" prefHeight=\"318.9998779296875\" prefWidth=\"168.0\" styleClass=\"layout\" xmlns:fx=\"http://javafx.com/fxml\" fx:controller=\"fruit.FruitComboController\">\n" +
      "  <children>\n" +
      "    <Label id=\"fruitSelectorLabel\" layoutX=\"15.0\" layoutY=\"10.0\" styleClass=\"bold-label\" text=\"Fruit Selector\" />\n" +
      "    <ComboBox fx:id=\"fruitCombo\" layoutX=\"15.0\" layoutY=\"33.0\" prefWidth=\"139.0\" promptText=\"choose\">\n" +
      "      <items>\n" +
      "        <FXCollections fx:factory=\"observableArrayList\">\n" +
      "          <String fx:value=\"Apple\" />\n" +
      "          <String fx:value=\"Orange\" />\n" +
      "          <String fx:value=\"Pear\" />\n" +
      "        </FXCollections>\n" +
      "      </items>\n" +
      "    </ComboBox>\n" +
      "    <VBox alignment=\"TOP_CENTER\" layoutX=\"14.0\" layoutY=\"62.0\" prefHeight=\"134.0\" prefWidth=\"140.0\" spacing=\"8.0\">\n" +
      "      <children>\n" +
      "        <StackPane id=\"selected-fruit-frame\" minHeight=\"100.0\" minWidth=\"118.0\" prefHeight=\"108.0\" prefWidth=\"140.0\">\n" +
      "          <children>\n" +
      "            <ImageView fx:id=\"orangeImage\" fitHeight=\"91.99999237060547\" fitWidth=\"122.66666035739114\" pickOnBounds=\"true\" preserveRatio=\"true\" visible=\"false\">\n" +
      "              <image>\n" +
      "                <Image url=\"http://i.i.com.com/cnwk.1d/i/tim/2011/03/10/orange_iStock_000001331357X_540x405.jpg\" preserveRatio=\"false\" smooth=\"false\" />\n" +
      "              </image>\n" +
      "            </ImageView>\n" +
      "            <ImageView fx:id=\"pearImage\" fitHeight=\"93.0\" fitWidth=\"124.0\" pickOnBounds=\"true\" preserveRatio=\"true\" visible=\"false\">\n" +
      "              <image>\n" +
      "                <Image url=\"http://smoothiejuicerecipes.com/pear.jpg\" preserveRatio=\"false\" smooth=\"false\" />\n" +
      "              </image>\n" +
      "            </ImageView>\n" +
      "            <ImageView fx:id=\"appleImage\" fitHeight=\"93.0\" fitWidth=\"124.0\" pickOnBounds=\"true\" preserveRatio=\"true\" visible=\"false\">\n" +
      "              <image>\n" +
      "                <Image url=\"http://uhallnyu.files.wordpress.com/2011/11/green-apple.jpg\" preserveRatio=\"false\" smooth=\"false\" />\n" +
      "              </image>\n" +
      "            </ImageView>\n" +
      "          </children>\n" +
      "        </StackPane>\n" +
      "        <Label fx:id=\"selectedFruit\" textAlignment=\"CENTER\" />\n" +
      "      </children>\n" +
      "    </VBox>\n" +
      "    <Button fx:id=\"saveValueButton\" layoutX=\"14.0\" layoutY=\"219.0\" mnemonicParsing=\"false\" onAction=\"#saveValue\" text=\"Save Value\" />\n" +
      "    <Label fx:id=\"valueLabel\" layoutX=\"15.0\" layoutY=\"273.0\" text=\"\" />\n" +
      "  </children>\n" +
//      "  <stylesheets>\n" +
//      "    <URL value=\"@fruitcombo.css\" />\n" +
//      "  </stylesheets>\n" +
      "</AnchorPane>\n";
}

Output (looks ugly without css, but still functional).

orangeimage

Controller class for completeness:

package fruit;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;

/** JavaFX fxml controller for fruit combo fxml demo application. */
public class FruitComboController implements Initializable {

  @FXML //  fx:id="appleImage"
  private ImageView appleImage; // Value injected by FXMLLoader

  @FXML //  fx:id="fruitCombo"
  private ComboBox<String> fruitCombo; // Value injected by FXMLLoader

  @FXML //  fx:id="orangeImage"
  private ImageView orangeImage; // Value injected by FXMLLoader

  @FXML //  fx:id="pearImage"
  private ImageView pearImage; // Value injected by FXMLLoader

  @FXML //  fx:id="selectedFruit"
  private Label selectedFruit; // Value injected by FXMLLoader

  @Override // This method is called by the FXMLLoader when initialization is complete
  public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
    assert appleImage != null : "fx:id=\"appleImage\" was not injected: check your FXML file 'fruitcombo.fxml'.";
    assert fruitCombo != null : "fx:id=\"fruitCombo\" was not injected: check your FXML file 'fruitcombo.fxml'.";
    assert orangeImage != null : "fx:id=\"orangeImage\" was not injected: check your FXML file 'fruitcombo.fxml'.";
    assert pearImage != null : "fx:id=\"pearImage\" was not injected: check your FXML file 'fruitcombo.fxml'.";
    assert selectedFruit != null : "fx:id=\"selectedFruit\" was not injected: check your FXML file 'fruitcombo.fxml'.";

    // bind the selected fruit label to the selected fruit in the combo box.
    selectedFruit.textProperty().bind(fruitCombo.getSelectionModel().selectedItemProperty());

    // listen for changes to the fruit combo box selection and update the displayed fruit image accordingly.
    fruitCombo.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
      @Override public void changed(ObservableValue<? extends String> selected, String oldFruit, String newFruit) {
        if (oldFruit != null) {
          switch(oldFruit) {
            case "Apple":  appleImage.setVisible(false);  break;
            case "Orange": orangeImage.setVisible(false); break;
            case "Pear":   pearImage.setVisible(false);   break;
          }
        }
        if (newFruit != null) {
          switch(newFruit) {
            case "Apple":  appleImage.setVisible(true);   break;
            case "Orange": orangeImage.setVisible(true);  break; 
            case "Pear":   pearImage.setVisible(true);    break;
          }
        }  
      }
    });
  }
}
4
5/15/2013 8:46:39 AM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon