3

我是 JavaFX 的新手,我尝试在 stackoverflow 和 google 中搜索此问题的解决方案,但找不到解决方案。

对不起,如果这是一个报告。

这是我的问题。我正在尝试从字符串加载 FXML,这可能吗?假设字符串结果包含 FXML 信息。

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

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

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

但是代码不起作用。

感谢你的帮助。

4

1 回答 1

4

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;
          }
        }  
      }
    });
  }
}
于 2013-05-15T08:46:39.580 回答