我创建了一个包含2个VBOX场景的舞台,每个VBOX应该包含4个将从FXML文件动态加载的节点。
我使用以下函数动态加载节点
@FXML VBox firstColumnBox; // will contain four loaded nodes
@FXML VBox secondColumnBox; // will also contain four loaded , so the scene will have a two columns screens with four nodes at right and four nodes at left
public void showPreviewOfCards(int size) {
for (int i = 0; i < size; i++) {
try {
FXMLLoader cardLoader = new FXMLLoader(getClass().getResource("CardEleveVerso.fxml"));
AnchorPane cardRoot = cardLoader.load();
if ((i == 0) || (i % 2 == 0)) {
firstColumnBox.getChildren().add(cardRoot);
} else {
secondColumnBox.getChildren().add(cardRoot);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
使用上述功能,我得到了预期的结果,但是问题是:“性能”。应用程序变得太慢,并且在netbeans中使用探查器时,它几乎占据了堆大小的全部量。
然后我对此进行了一些更改
@FXML VBox firstColumnBox;
@FXML VBox secondColumnBox;
public void showPreviewOfCards() {
int size = listofStudentToPrint.size();
try {
FXMLLoader cardLoader = new FXMLLoader(getClass().getResource("CardeEleve.fxml"));
AnchorPane card = (AnchorPane) cardLoader.load();
CardeEleveController controller = (CardeEleveController) cardLoader.getController();
for (int i = 0; i < size; i++) {
StudentModel student = listofStudentToPrint.get(i);
student.setCardNo(String.valueOf(totalNoOfCard++));
controller.setValues(student);
if ((i == 0) || (i % 2 == 0)) {
firstColumnBox.getChildren().add(card);
} else {
secondColumnBox.getChildren().add(card);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
这一次,我将负责加载fxml的代码行放在“ for循环”之外,以便在循环内部,我将仅通过使用节点的fxml控制器设置新值来重用已经加载的节点。
这是问题开始的地方,无论我添加了多少节点,在我的两栏中我都只会看到一个已加载的节点。
这是舞台场景的FXML文件
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.TilePane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="612.0"
styleClass="mainFxmlClass" xmlns="http://javafx.com/javafx/11.0.1"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="monanocard.PrintCardRectoController">
<stylesheets>
<URL value="@printcardrecto.css"/>
</stylesheets>
<children>
<BorderPane prefHeight="400.0" prefWidth="635.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<bottom>
<HBox alignment="CENTER_RIGHT" prefHeight="37.0"
prefWidth="648.0" BorderPane.alignment="CENTER_RIGHT">
<children>
<Button fx:id="btnPrint" mnemonicParsing="false"
prefHeight="32.0" prefWidth="121.0" style="-fx-background-color:
green;" text="IMPRIMER" textFill="WHITE">
<graphic>
<ImageView fitHeight="22.0" fitWidth="31.0"
pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../icons/ic_print.png"/>
</image>
</ImageView>
</graphic>
</Button>
</children>
<BorderPane.margin>
<Insets bottom="5.0" right="10.0" top="5.0"/>
</BorderPane.margin>
</HBox>
</bottom>
<center>
<AnchorPane BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets/>
</BorderPane.margin>
<children>
<ScrollPane fx:id="scrollPane" fitToHeight="true"
fitToWidth="true">
<content>
<TilePane fx:id="twoColumnsContainer"
alignment="TOP_CENTER" hgap="1.0" maxWidth="-Infinity" minHeight="-
Infinity" minWidth="-Infinity" prefColumns="2" prefRows="8"
prefWidth="655.0" tileAlignment="TOP_CENTER" vgap="1.0">
<children>
<VBox fx:id="secondColumnBox"
alignment="TOP_CENTER" maxWidth="-Infinity" prefHeight="220.0"
prefWidth="315.0"/>
<VBox fx:id="firstColumnBox"
alignment="TOP_CENTER" maxWidth="-Infinity" prefHeight="220.0"
prefWidth="315.0"/>
</children>
</TilePane>
</content>
</ScrollPane>
</children>
</AnchorPane>
</center>
</BorderPane>
</children>
</AnchorPane>
这里是FXML文件,其中包含动态加载的节点的设计
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="176.0" prefWidth="310.0" style="-fx-background-color: white;" styleClass="card"
xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="monanocard.CardeEleveController">
<stylesheets>
<URL value="@cardeeleve.css"/>
</stylesheets>
<children>
<BorderPane layoutX="3.0" layoutY="3.0" prefHeight="156.0" prefWidth="307.0" AnchorPane.bottomAnchor="2.0"
AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0">
<center>
<AnchorPane maxHeight="-Infinity" prefHeight="105.0" prefWidth="259.0" style="-fx-background-color: white;"
BorderPane.alignment="CENTER">
<children>
<ImageView fx:id="imageProfile" fitHeight="84.0" fitWidth="87.0" layoutX="6.0" layoutY="8.0"
pickOnBounds="true">
<image>
<Image url="@../icons/ben.jpg"/>
</image>
</ImageView>
<VBox alignment="TOP_CENTER" layoutX="100.0" layoutY="3.0" prefHeight="100.0" prefWidth="188.0"
spacing="2.0">
<children>
<HBox prefHeight="11.0" prefWidth="202.0">
<children>
<Label prefHeight="11.0" prefWidth="72.0" text="Nom">
<font>
<Font name="Roboto Bold" size="7.0"/>
</font>
</Label>
<Label fx:id="lblNom" prefHeight="4.0" prefWidth="97.0">
<font>
<Font name="System Bold" size="7.0"/>
</font>
</Label>
</children>
</HBox>
<HBox prefHeight="0.0" prefWidth="212.0">
<children>
<Label prefHeight="11.0" prefWidth="87.0" text="Postnom">
<font>
<Font name="Roboto Bold" size="7.0"/>
</font>
</Label>
<Label fx:id="lblPostnom" prefHeight="2.0" prefWidth="129.0">
<font>
<Font name="System Bold" size="7.0"/>
</font>
</Label>
</children>
</HBox>
<HBox prefHeight="0.0" prefWidth="212.0">
<children>
<Label prefHeight="11.0" prefWidth="86.0" text="Prenom">
<font>
<Font name="Roboto Black" size="7.0"/>
</font>
</Label>
<Label fx:id="lblPrenom" prefHeight="0.0" prefWidth="129.0">
<font>
<Font name="System Bold" size="7.0"/>
</font>
</Label>
</children>
</HBox>
<HBox prefHeight="0.0" prefWidth="212.0">
<children>
<Label prefHeight="11.0" prefWidth="84.0" text="Matricule">
<font>
<Font name="Roboto Bold" size="7.0"/>
</font>
</Label>
<Label fx:id="lblMatricule" prefHeight="0.0" prefWidth="129.0">
<font>
<Font name="System Bold" size="7.0"/>
</font>
</Label>
</children>
</HBox>
<HBox prefHeight="6.0" prefWidth="212.0">
<children>
<Label prefHeight="11.0" prefWidth="87.0" text="Classe">
<font>
<Font name="Roboto Black" size="7.0"/>
</font>
</Label>
<Label fx:id="lblClasse" prefHeight="9.0" prefWidth="129.0">
<font>
<Font name="System Bold" size="7.0"/>
</font>
</Label>
</children>
</HBox>
<HBox prefHeight="11.0" prefWidth="211.0">
<children>
<Label prefHeight="11.0" prefWidth="84.0" text="Sexe">
<font>
<Font name="Roboto Bold" size="7.0"/>
</font>
</Label>
<Label fx:id="lblSexe" prefHeight="0.0" prefWidth="129.0">
<font>
<Font name="System Bold" size="7.0"/>
</font>
</Label>
</children>
</HBox>
<HBox prefHeight="21.0" prefWidth="211.0">
<children>
<Label alignment="TOP_LEFT" prefHeight="16.0" prefWidth="70.0" text="Adresse">
<font>
<Font name="Roboto Black" size="7.0"/>
</font>
</Label>
<Label fx:id="lblAddresse" alignment="TOP_LEFT" prefHeight="27.0" prefWidth="101.0" wrapText="true">
<font>
<Font name="System Italic" size="5.0"/>
</font>
</Label>
</children>
</HBox>
</children>
<padding>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0"/>
</padding>
</VBox>
</children>
</AnchorPane>
</center>
<bottom>
<VBox alignment="CENTER" prefHeight="18.0" prefWidth="295.0" BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0"/>
</BorderPane.margin>
<children>
<Label fx:id="lblValidity" alignment="CENTER" layoutX="100.0" prefHeight="23.0" prefWidth="295.0">
<font>
<Font name="Felix Titling" size="9.0"/>
</font>
<padding>
<Insets bottom="2.0"/>
</padding>
</Label>
</children>
</VBox>
</bottom>
<top>
<HBox maxWidth="-Infinity" prefHeight="43.0" prefWidth="302.0" style="-fx-padding: 5;" styleClass="top"
stylesheets="@cardeeleve.css" BorderPane.alignment="CENTER">
<children>
<ImageView fitHeight="29.0" fitWidth="36.0" pickOnBounds="true">
<image>
<Image url="@../icons/monano_logo.jpg"/>
</image>
</ImageView>
<VBox prefHeight="29.0" prefWidth="212.0">
<children>
<Label alignment="CENTER" prefHeight="11.0" prefWidth="219.0" text="CS MONANO 1">
<font>
<Font name="Arial Black" size="10.0"/>
</font>
</Label>
<Label fx:id="lblCardNo" alignment="CENTER" prefHeight="11.0" prefWidth="220.0">
<font>
<Font name="Arial" size="8.0"/>
</font>
</Label>
</children>
</VBox>
<ImageView fitHeight="28.0" fitWidth="34.0" pickOnBounds="true">
<image>
<Image url="@../icons/rdc_flag.png"/>
</image>
</ImageView>
</children>
</HBox>
</top>
</BorderPane>
</children>
</AnchorPane>
以及加载的Node的控制器
public class CardeEleveController implements Initializable {
@FXML Label lblDevise;
@FXML Label lblValidity;
@FXML Label lblNom;
@FXML Label lblPostnom;
@FXML Label lblPrenom;
@FXML Label lblClasse;
@FXML Label lblSexe;
@FXML Label lblAddresse;
@FXML Label lblCardNo;
@FXML Label lblMatricule;
@FXML ImageView imageProfile;
String serverAddress = FXMLDocumentController.configuration.get(ConfigurationHandler.OPTION_SERVER_ADDRESSE);
String serverPort = FXMLDocumentController.configuration.get(ConfigurationHandler.OPTION_SERVER_PORT);
String site = FXMLDocumentController.configuration.get(ConfigurationHandler.OPTION_SERVER_SITE);
String photoSite = FXMLDocumentController.configuration.get(ConfigurationHandler.OPTION_PHOTO_SITE);
String validite = FXMLDocumentController.configuration.get(ConfigurationHandler.OPTION_VALIDITY);
private static boolean IS_OPERATION_MODE = false;
@Override
public void initialize(URL url, ResourceBundle rb) {
String currentMode = FXMLDocumentController.CURRENT_MODE;
if (currentMode.equalsIgnoreCase("operation")) {
IS_OPERATION_MODE = true;
}
}
public void setValues(StudentModel student) {
if (student != null) {
System.out.println("Controller setting values...");
System.out.println();
System.out.println("------------------------------");
System.out.println("NAME: " + student.getNom() + " " + student.getPostnom() + " " + student.getPrenom());
System.out.println("------------------------------");
String cardNoTxt = "Carte d'Eleve No " + generateCardNoBasedNoOfDigit(Integer.parseInt(student.getCardNo()));
lblCardNo.setText(cardNoTxt);
lblNom.setText(student.getNom());
lblPostnom.setText(student.getPostnom());
lblPrenom.setText(student.getPrenom());
lblClasse.setText(student.getClasse());
lblMatricule.setText(student.getMatricule());
lblSexe.setText(student.getSexe());
AddressModel address = student.getAddress();
String addresseString = address.getAv() + " No." + address.getNo() + "Q. " + address.getQuartier() + "\n" + "C." + address.getCommune();
lblAddresse.setText(addresseString);
String imagePath = student.getPhotoUrl();
if (IS_OPERATION_MODE) {
//construct photo url
String photoUrl = "http://" + serverAddress + ":" + serverPort + "/" + photoSite + "/" + Utility.STUDENT_IMAGE_DIRECTORY + "/" + imagePath;
Image image = new Image(photoUrl, 100, 100, false, false);
imageProfile.setImage(image);
} else {
// to use during formation Mode
// load the image saved locally
if (imagePath != null && !imagePath.isEmpty()) {
Image image = new Image("file:" + student.getPhotoUrl(), 100, 100, false, false);
imageProfile.setImage(image);
}
}
if (validite != null) {
// get the two values separated by :
Scanner scanner = new Scanner(validite);
scanner.useDelimiter(":");
String fromDate = scanner.next();
String toDate = scanner.next();
String valideString = "Valide Du " + fromDate + " Au " + toDate;
lblValidity.setText(valideString);
}
}
}
}
总而言之,我希望能够动态加载节点而不会出现性能问题。