如何在JavaFX中从字符串加载FXML

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);  

但是这段代码无法工作。

非常感谢您的帮助。


“但是代码无法运行”并不是一个有用的陈述,不能得到一个好的答案 - 总是解释一下为什么它不能工作,并提供错误输出、屏幕截图等不正确的行为。 - jewelsea
1个回答

4

将FXML从字符串加载对我有效(Java 8b89,OS X 10.8)

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

请注意,相对引用无法工作。例如,在下面的示例代码中,CSS样式表包含被注释掉了,因为它需要一个完整的URL而不仅仅是一个相对文件名来解析(当从InputStream加载时,没有相对路径可用于解析)。以下是将FXML从字符串而不是文件加载的FXML示例的改编版本:
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";
}

输出(没有CSS看起来很丑,但仍然可用)。

橙色图片

控制器类以完整性为例:

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;
          }
        }  
      }
    });
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接