Root value already specified Exception in CustomController while loading a FXML - java

first of all: I have tried:
fxml loader exception "root value is already specified" I never specified a root value
javafx exception : Controller value already specified
LoadException: Root value already specified on custom control
But no solution worked for me: I deleted the fx:controller tag from my FXML -> Exception, added fx:root type="BorderPanealways the same Exception:
Caused by: java.lang.RuntimeException: javafx.fxml.LoadException: Root value already specified
When I remove the statement fxmlLoader.setRoot(this) from my custom controller no Exception is thrown but the layout is empty. For better understanding, below are my code snippets from my MainScreenController where I want to add the custom controller as child and my CustomController class ImageContainer
Help is appreciated!
Code snippet MainScreenController (only a snippet):
public class MainScreenController{
public TextField tf_userName;
public ListView lv_listView;
public FlowPane fp_contentFlowPane;
public SplitPane sp_splitPane;
public void onItemClicked(MouseEvent mouseEvent) throws IOException {
int index = lv_listView.getSelectionModel().getSelectedIndex();
if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {
if (index >= 0) {
lv_listView.getItems().remove(index);
userList.remove(index);
}
}
else{
ImageContainer imgC = new ImageContainer(4,2,"location");
fp_contentFlowPane.getChildren().add(imgC);
}
}}
Code of my Custom controller, ImageContainer:
public class ImageContainer extends Pane {
public HBox hbx_elementContainer;
public Label lb_likeCount;
public Label lb_commentCount;
public Label lb_location;
public Label lb_accountHolder;
public ImageView iv_feedImage;
private String imageLink;
public ImageContainer(int likeCount, int commentCount, String location) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/image_container.fxml"));
fxmlLoader.setController(this);
fxmlLoader.setRoot(this);
try {
fxmlLoader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
this.lb_likeCount.setText(String.valueOf(likeCount));
this.lb_commentCount.setText(String.valueOf(commentCount));
this.lb_location.setText(location);
Image image = new Image("/sampleFoto.JPG");
iv_feedImage.setImage(image);
}
}
FXML file of the layout I want to set:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1">
<bottom>
<HBox fx:id="hbx_elementContainer" prefHeight="31.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<children>
<Label fx:id="lb_likeCount" contentDisplay="TOP" text="Label">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin></Label>
<Label fx:id="lb_commentCount" text="Label">
<HBox.margin>
<Insets right="20.0" />
</HBox.margin></Label>
<Label fx:id="lb_location" text="Label" />
<Label fx:id="lb_accountHolder" text="Label" />
<Button mnemonicParsing="false" text="Download">
<font>
<Font name="Arial Bold" size="11.0" />
</font>
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</bottom>
<center>
<AnchorPane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<ImageView fx:id="iv_feedImage" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</center>
</BorderPane>

Related

Javafx Path to a specific folder and select the file entered on textfield

I wasn't very clear on my previous question, and I just rephrased it. Here is what I trying to achieve.
I want to define a path to a folder;
on the FROM ->TextField, Customer will enter the image name which already exist in the folder;
Click on a button and the file name will be added to the path and populate it to the imageView without manually browsing to the folder.
So, how can I do that? Thanks
ImageViewerController .java
public class ImageViewerController implements Initializable {
private Label label;
#FXML
private ImageView imageView;
#FXML
private TextField txt_Path;
private Image image;
String name;
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
private void btn_Valide(ActionEvent event) {
loadImage();
}
private void loadImage(){
name = txt_Path.getText();
File file = new File("src/images/"+name);
Image image = new Image(file.toURI().toString());
imageView.setImage(image);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="521.0" prefWidth="660.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="imageviewer.ImageViewerController">
<center>
<Pane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<Pane layoutX="24.0" layoutY="248.0" prefHeight="248.0" prefWidth="306.0" style="-fx-background-color: #EBDEF0;">
<children>
<ImageView fx:id="imageView" fitHeight="237.0" fitWidth="297.0" layoutX="7.0" layoutY="8.0" pickOnBounds="true" preserveRatio="true" />
</children>
</Pane>
<TextField fx:id="txt_Path" layoutX="24.0" layoutY="28.0" prefHeight="25.0" prefWidth="510.0" text="avatar.jpg" />
<Button layoutX="549.0" layoutY="28.0" mnemonicParsing="false" onAction="#btn_Valide" prefHeight="25.0" prefWidth="77.0" text="Valide" />
</children>
</Pane>
</center>
</BorderPane>

Can't pass attribute betwewen scenes JAvaFX

I'm trying to pass a String between scenes in JavaFX, I already followed the some answers but it seems that they don't work because the string is null in the new scene.
Here's my MainControler:
public class FXMLDocumentController implements Initializable {
#FXML
private Button btn_signup;
#FXML
private TextField et_username;
#FXML
private PasswordField et_password;
#FXML
private Hyperlink link_login;
Stage prevStage;
public void setPrevStage(Stage stage){
this.prevStage = stage;
}
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
if(btn_signup == event.getSource()){
Conector conn = new Conector();
if (conn.checkUser(et_username.getText(), et_password.getText())) {
FXMLLoader myLoader = new FXMLLoader(getClass().getResource("FXMLTasker.fxml"));
Pane myPane = (Pane)myLoader.load();
Scene scene = new Scene(myPane);
Stage stage = new Stage();
stage.setResizable(false);
stage.setScene(scene);
FXMLTaskerController controler = new FXMLTaskerController();
controler.setUser(et_username.getText());
myLoader.setController(controler);
prevStage.close();
stage.show();
}else {
JOptionPane.showMessageDialog(null, "Usuario o ContraseƱa incorrecta");
}
}else if (link_login == event.getSource()){
System.out.println("Registrate!");
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Here's the other class controler, the one where i want my String.
public class FXMLTaskerController implements Initializable {
#FXML private ListView list_todo;
#FXML private ListView list_done;
#FXML public String username;
private void handleButtonAction(ActionEvent event) {
}
#Override
public void initialize(URL url, ResourceBundle rb) {
System.out.println(username);
list_todo.setCellFactory(new TaskCellFactory());
list_done.setCellFactory(new TaskCellFactory());
try {
getTasks();
} catch (IOException ex) {
Logger.getLogger(FXMLTaskerController.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void setUser(String username){
this.username = username;
}
public void getTasks() throws IOException{
Conector con = new Conector();
for(Task task: con.obtenerTareas("pepin")){
System.out.println(task);
if(task.isState()){
list_done.getItems().add(task);
}else{
list_todo.getItems().add(task);
}
}
}
}
And here are the fxml files:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="400.0" prefWidth="500.0" style="-fx-background-color: #0288D1; -fx-border-color: #01579B; -fx-border-width: 5;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="desktop_tasker.FXMLDocumentController">
<children>
<Label layoutX="215.0" layoutY="34.0" text="Sign In" textFill="WHITE">
<font>
<Font size="23.0" />
</font>
</Label>
<Hyperlink fx:id="link_login" layoutX="150.0" layoutY="269.0" onAction="#handleButtonAction" text="Not registered yet? Click here." textFill="WHITE" />
<TextField fx:id="et_username" layoutX="21.0" layoutY="102.0" prefHeight="25.0" prefWidth="425.0" promptText="Username" style="-fx-prompt-text-fill: #ffffff; -fx-background-color: #0288D1;" />
<Separator layoutX="27.0" layoutY="126.0" prefHeight="3.0" prefWidth="425.0" />
<Separator layoutX="27.0" layoutY="192.0" prefHeight="3.0" prefWidth="425.0" />
<Button fx:id="btn_signup" layoutX="27.0" layoutY="222.0" mnemonicParsing="false" onAction="#handleButtonAction" prefHeight="23.0" prefWidth="425.0" style="-fx-background-color: #FFA000; -fx-prompt-text-fill: #ffffff;" text="SignUp" textFill="WHITE" />
<PasswordField fx:id="et_password" layoutX="21.0" layoutY="167.0" prefHeight="25.0" prefWidth="425.0" promptText="Password" style="-fx-background-color: #0288D1; -fx-prompt-text-fill: #ffffff;" />
</children>
</AnchorPane>
And the other one:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="557.0" prefWidth="1012.0" style="-fx-background-color: #0288D1;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="desktop_tasker.FXMLTaskerController">
<children>
<SplitPane dividerPositions="0.5811881188118811" layoutX="-8.0" layoutY="35.0" prefHeight="529.0" prefWidth="1027.0" style="-fx-background-color: #EEEEEE;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="28.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView fx:id="list_todo" layoutY="-8.0" prefHeight="527.0" prefWidth="584.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView fx:id="list_done" layoutY="14.0" prefHeight="527.0" prefWidth="420.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children></AnchorPane>
</items>
</SplitPane>
<MenuBar prefHeight="30.0" prefWidth="1012.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</AnchorPane>
As you can see I tried to use a controler and using a set pasing the String, the problem is that when I open the new scene, his controler resets and the String is no longer there, any idea why or how to solve this?
If you want to set a Controller with myLoader.setController(controler); you must do it before calling Pane myPane = (Pane)myLoader.load(); and also remove fx:controller="desktop_tasker.FXMLTaskerController" from FXMLTasker.fxml, else you get a LoadException: Controller value already specified.
See JavaDoc FXMLLoader.setController(Object controller):
Sets the controller associated with the root object. The value passed to this method is used as the value of the fx:controller attribute. This method must be called prior to loading the document when using controller event handlers when an fx:controller attribute is not specified in the document.
Alternatively you can request the Controller from FXMLLoader:
FXMLTaskerController controler = (FXMLTaskerController)myLoader.getController();
controler.setUser(et_username.getText());
But thereby you can't assume that username is set in initialize(URL url, ResourceBundle rb) and should removed from there.

How to find FXML variable by id dynamically in javafx?

I am trying to create an HTML editor (learning purposes) and I am trying to make program as dynamic as possible. I want to find FXML variable, like TextField, by it's id and retrieve the text in the textfield when I press the button.
I have 2 Map variables set up
public FXMLDocumentController() {
this.HTMLtags = new HashMap<>();
HTMLtags.put("pressMeButton", "h2.fx-h2");
HTMLtags.put("setNewsMessageButton", "p.fx-message");
this.elementsMap = new HashMap<>();
elementsMap.put("pressMeButton", "newsTitle");
elementsMap.put("setNewsMessageButton", "newsMessage");
}
HTMLtags holds the button ID and HTML tag, which is going to be edited.
elementsMap holds button ID and TextView ID that it suppose to grab text from. Kinda like "binding specific button to specific textfield".
private void changeText(ActionEvent event) throws IOException {
Object source = event.getSource();
Button clickedButton = (Button) source;
System.out.println(HTMLtags.get(clickedButton.getId()));
System.out.println(elementsMap.get(clickedButton.getId()));
writeToHTML(HTMLtags.get(clickedButton.getId()), elementsMap.get(clickedButton.getId()));
}
Method above correctly retrieves IDs of buttons and HTML tags that need to be edited.
Here is the code that sets the text in the HTML
private void writeToHTML(String HTMLTag, String textField) {
File input = new File(filePath);
Document doc;
try {
doc = Jsoup.parse(input, "UTF-8");
Element head = doc.select(HTMLTag).first();
originalText = head.toString();
TextField textFieldName = new TextField();
textFieldName.setId(textField);
head.text(textFieldName.getText());
System.out.println("Original Text is: " + originalText);
System.out.println("Modified Text is: " + head);
Path path = Paths.get(filePath);
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll(originalText, head.toString());
Files.write(path, content.getBytes(charset));
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
The problem is that I dunno how to find and retrieve text from textfield specifically in this part of code
TextField textFieldName = new TextField();
textFieldName.setId(textField);
head.text(textFieldName.getText());
I want to do it dynamically without declaring each FXML element through
#FXML private TextField "name of the fx:id" and matching each element through loop.
I want to do it similar to the way I get ID/value of the button through ActionEvent.
EDIT:
here is the full FXML btw
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.66" xmlns:fx="http://javafx.com/fxml/1" fx:controller="newsletter.editor.FXMLDocumentController">
<children>
<ScrollPane fitToWidth="true" prefHeight="800.0" prefWidth="1280.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<VBox alignment="CENTER" prefHeight="450.0">
<children>
<HBox alignment="CENTER">
<children>
<Label alignment="CENTER" minHeight="25.0" minWidth="192.0" prefHeight="50.0" prefWidth="192.0" text="Newsletter Title" wrapText="true">
<font>
<Font size="18.0" />
</font>
</Label>
<TextField id="newsTitle" fx:id="newsTitle" prefHeight="28.0" prefWidth="180.0" promptText="Write here" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<TextArea fx:id="newsMessage" prefHeight="100.0" prefWidth="766.0" />
</children>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0" />
<HBox prefHeight="100.0" prefWidth="200.0" />
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Button fx:id="setNewsMessageButton" mnemonicParsing="false" onAction="#changeText" text="MAGIC" />
<Button fx:id="pressMeButton" mnemonicParsing="false" onAction="#changeText" text="Press Me for Magic">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
<Button fx:id="filePathButton" mnemonicParsing="false" onAction="#filePathSave" text="Select Path">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
<Button fx:id="popoverButton" mnemonicParsing="false" onAction="#popOverTrigger" text="PopOver Test">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</children>
<padding>
<Insets left="20.0" right="20.0" />
</padding>
</VBox>
</content>
</ScrollPane>
</children>
</AnchorPane>
You can perform an id lookup to find the TextField.
Parent parent = getTextFieldParent(); // the Parent (or Scene) that contains the TextFields
TextField textField = (TextField) parent.lookup("#myTextField");
if (textField != null)
String text = textField.getText();
Yes, your need method lookup(). Not only Parent class has this method, it also has at Panel classes like FlowPane, AnchorPane and many other. Also this method in Scene class.
But! This method looking only after scene show. I don't now, why it happens, but before Scene show(), lookup() only finds top-level panel. And after show() it finds element by id, like scene.lookup("#myId");
Symbol # is required.
Also lookup() method can find element without id, by the type.
Example: scene.lookup("FlowPane"); (without #) will find the first FlowPane in your .fxml file. And scene.lookupAll("ImageView"); will return the massive with all ImageView elements in scene.

JavaFX create and use custom control with it's own functions

I have created a simple custom control as shown in picture:
when I click on "Click me" button the console shows me this message "The button was clicked!" by a function called doSomething, and this is the custom control's fxml file code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<fx:root prefHeight="83.0" prefWidth="196.0" type="javafx.scene.layout.AnchorPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextField fx:id="textField" layoutY="2.0" prefHeight="25.0" prefWidth="196.0" />
<Button layoutX="72.0" layoutY="29.0" mnemonicParsing="false" onAction="#doSomething" text="Click me" />
</children>
</fx:root>
And this is the controller of this custom control:
package control;
import java.io.IOException;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
public class Controller extends AnchorPane {
#FXML private TextField textField;
public Controller() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("CustomControlView.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public String getText() {
return textProperty().get();
}
public void setText(String value) {
textProperty().set(value);
}
public StringProperty textProperty() {
return textField.textProperty();
}
#FXML
protected void doSomething() {
System.out.println("The button was clicked!");
}
}
The control is working good and I can call it in another fxml file using "JavaFX scence builder" (as shown in picture) :
And this is the fxml file code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="237.0" prefWidth="324.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<javafx.scene.layout.AnchorPane layoutX="64.0" layoutY="92.0" prefHeight="40.0" prefWidth="196.0">
<children>
<TextField fx:id="textField" layoutY="2.0" prefHeight="25.0" prefWidth="196.0" />
<Button layoutX="72.0" layoutY="29.0" mnemonicParsing="false" onAction="#doSomething" text="Click me" />
</children>
</javafx.scene.layout.AnchorPane>
<Label layoutX="75.0" layoutY="14.0" text="Trying the custom control:">
<font>
<Font size="15.0" />
</font>
</Label>
</children>
</AnchorPane>
But the problem is that I have to redefine the doSomething function of the custom control button !!!I mean when I added my custom conrol to another fxml file all the functions of this custom control should work without redefining it just like Swing.
Am I wrong ?
The problem is that the Scene Builder just copies the code of your custom control into the new control rather than linking it. To use your custom control you have to use the fx:include FXML tag.
So the FXML file should look something like:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="237.0" prefWidth="324.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<fx:include source="yourCustomControl.fxml" />
<Label layoutX="75.0" layoutY="14.0" text="Trying the custom control:">
<font>
<Font size="15.0" />
</font>
</Label>
</children>
</AnchorPane>
However, you have to do this manually. As far as I know, the Scene Builder is not capable of doing it.

Why is ImageView not injected through JavaFX FXML?

I'm having a problem getting my ImageView component injected through FXMl in JavaFX. I have a controller written in Scala as so:
package me.mycontroller
import javafx.fxml.FXML
import java.util.ResourceBundle
import java.net.URL
import javafx.scene.image.ImageView
/**
* #author me
*/
class InvoiceController {
#FXML
private var resources: ResourceBundle = null
#FXML
private var location: URL = null
#FXML
private var imageBox2: ImageView = null
#FXML
def initialize() {
if(imageBox2==null) { throw new IllegalArgumentException("imageBox was null")}
}
}
and my FXMl is like so:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.collections.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="286.0" prefWidth="512.0" xmlns:fx="http://javafx.com/fxml" fx:controller="me.mycontroller.InvoiceController">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="435.0" spacing="10.0" AnchorPane.bottomAnchor="58.0" AnchorPane.leftAnchor="38.5" AnchorPane.rightAnchor="38.5" AnchorPane.topAnchor="128.0">
<children>
<Label text="Invoice File" />
<TextField fx:id="fileField" prefWidth="200.0" />
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="400.5" spacing="10.0" AnchorPane.bottomAnchor="-7.0" AnchorPane.leftAnchor="52.5" AnchorPane.rightAnchor="59.0" AnchorPane.topAnchor="193.0">
<children>
<AnchorPane prefHeight="100.0" prefWidth="376.0">
<children>
<AnchorPane layoutX="16.0" layoutY="0.0" prefHeight="100.0" prefWidth="294.0">
<children>
<Label layoutY="42.0" prefWidth="65.0" text="Supplier" AnchorPane.leftAnchor="25.0" />
<ChoiceBox fx:id="supplierDropDown" layoutY="40.0" prefWidth="200.0" AnchorPane.rightAnchor="5.0">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Item 1" />
<String fx:value="Item 2" />
<String fx:value="Item 3" />
</FXCollections>
</items>
</ChoiceBox>
</children>
</AnchorPane>
</children>
</AnchorPane>
</children>
</HBox>
<ImageView fx:id="imageBox2" fitHeight="105.99999961206467" fitWidth="141.3333282470703" layoutX="53.0" layoutY="22.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../images/Regional.jpeg" />
</image>
</ImageView>
</children>
</AnchorPane>
When I run the program like:
Parent root = FXMLLoader.load(getClass().getResource("/fxml/Invoice.fxml"));
I get an exception because imageBox2 is null. Any idea why it's not getting injected?
src/
main/
Main.java
MainLayoutController.java
main_layout.fxml
...
MainLayoutController.java:
public class MainLayoutController {
#FXML
private ImageView previewImage;
void setImage(Image img) {
previewImage.setImage(img);
}
}
main_layout.fxml:
<VBox ... fx:controller="main.MainLayoutController">
<children>
...
<ImageView fx:id="previewImage" ... />
</children>
</VBox>
Main.java:
public class Main extends Application {
private MainLayoutController mainLayoutController;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader();
Parent root = fxmlLoader.load(
getClass().getResource("main_layout.fxml").openStream());
primaryStage.setScene(new Scene(root));
primaryStage.show();
mainLayoutController = fxmlLoader.getController();
mainLayoutController.setImage(...);
}
...
}

Categories