I am a beginner and I am trying to build a simple dictionary application.
I have a controller class which has a button to open a new dialog to input the various details.
The dialog is controlled by a separate controller and this is where I am experiencing problems, my FXML elements are given the value of null, hence I get a nullpointerexception when I run the code. I've annotated the FXML vaiables with #FXML and have checked that the fx:id in the fxml file matches that of the java file.
Here is the Controller.java code:
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.BorderPane;
import javafx.scene.control.Dialog;
import java.io.IOException;
import java.util.Optional;
public class Controller {
#FXML
private BorderPane mainBorderPane;
#FXML
private DialogController controller = new DialogController();
#FXML
public void initialize(){
}
#FXML
public void newItemDialog(){
Dialog <ButtonType> dialog = new Dialog<>();
dialog.initOwner(mainBorderPane.getScene().getWindow());
dialog.setTitle("Insert Word");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("newDialog.fxml"));
try{
dialog.getDialogPane().setContent(fxmlLoader.load());
}catch(IOException e) {
e.printStackTrace();
return;
}
dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
Optional<ButtonType> result = dialog.showAndWait();
if(result.isPresent() && result.get() == ButtonType.OK){
boolean results = controller.processResults();
}else{
System.out.println("Cancelled");
return;
}
}
}
Here is the DialogController.java code:
package sample;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import sample.control.Data;
import java.io.IOException;
import java.util.Optional;
public class DialogController {
#FXML
private TextField nameField;
#FXML
private TextField descriptionField;
#FXML
private TextField typeField;
#FXML
private TextField sentenceField;
#FXML
public boolean processResults() {
String name = nameField.getText();
String description = descriptionField.getText();
String type = typeField.getText();
String sentence = sentenceField.getText();
return Data.getInstance().addWord(name,type,description,sentence);
}
}
Here is the sample.fxml code:
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.ListView?>
<?import java.lang.String?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>
<BorderPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml"
fx:id ="mainBorderPane">
<top>
<MenuBar>
<Menu fx:id="fileButton" text="File">
<MenuItem fx:id="newButton" onAction="#newItemDialog" text="New"/>
<MenuItem fx:id="updateButton" text="Update"/>
<MenuItem fx:id="deleteButton" text="Delete"/>
<MenuItem fx:id="saveButton" text="Save"/>
</Menu>
<Menu fx:id="viewButton" text="View">
<MenuItem text="Dark Mode"/>
</Menu>
</MenuBar>
</top>
<left>
<ListView fx:id="wordListView" BorderPane.alignment="TOP_LEFT" prefHeight="Infinity" prefWidth="250">
</ListView>
</left>
<center>
<VBox>
<TextArea fx:id = "wordDetails" prefWidth="Infinity" prefHeight="400">
</TextArea>
<TextArea prefWidth="Infinity" prefHeight="200">
</TextArea>
</VBox>
</center>
</BorderPane>
Here is the newDialog.fxml code:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.DialogPane?>
<DialogPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.DialogController"
prefHeight="400.0" prefWidth="600.0">
<headerText>
Enter A Word
</headerText>
<content>
<VBox>
<TextField fx:id="nameField" promptText="Enter the word"/>
<TextField fx:id="typeField" promptText="Enter the type"/>
<TextField fx:id="descriptionField" promptText="Enter a description"/>
<TextField fx:id="sentenceField" promptText="Enter a sentence"/>
</VBox>
</content>
Thanks in advance!
The #FXML annotation indicates a field that should be initialized by the FXMLLoader to reference objects created corresponding to elements in an FXML file when the FXML file is loaded. Consequently:
It only makes sense to annotate fields #FXML if they correspond to elements in the FXML file
It never makes sense to initialize a field if it is annotated #FXML (because the FXMLLoader is supposed to initialize it)
Your DialogController field
#FXML
private DialogController controller = new DialogController();
doesn't make sense for both of these reasons: there is no DialogController element in the sample.fxml, and if there were, there would be no point in initializing the field.
A controller is a specific object associated with the UI loaded from an FXML file. The association is made by the FXMLLoader when it loads the FXML file. If you load the FXML file multiple times (as you appear to do here, since you are loading newDialog.fxml in an event handler), then (of course) you get new instances of all the elements in the FXML each time, and consequently a new instance of the controller class each time.
The object you create with
#FXML private DialogController controller = new DialogController();
is not the controller for any UI loaded any of the times you load newDialog.fxml; it is just another object of the same class. It is not clear whether you expect this field to somehow reference the controller created the first time the user chooses "New" from the menu, or the one created the second time they choose that menu item, etc. Or, of course, how you would expect it to refer to any of those controllers when you are initializing it before you ever load newDialog.fxml.
You get the controller from the FXMLLoader after loading the FXML. So you just need:
public class Controller {
#FXML
private BorderPane mainBorderPane;
#FXML
public void initialize(){
}
#FXML
public void newItemDialog(){
Dialog <ButtonType> dialog = new Dialog<>();
dialog.initOwner(mainBorderPane.getScene().getWindow());
dialog.setTitle("Insert Word");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("newDialog.fxml"));
try{
dialog.getDialogPane().setContent(fxmlLoader.load());
}catch(IOException e) {
e.printStackTrace();
return;
}
dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
Optional<ButtonType> result = dialog.showAndWait();
DialogController controller = fxmlLoader.getController();
if(result.isPresent() && result.get() == ButtonType.OK){
boolean results = controller.processResults();
}else{
System.out.println("Cancelled");
return;
}
}
}
Related
I made a custom control CustomControl in JavaFX.
The CustomControl is basically just a button and a text field. It is made of a CustomControl.fxml and a controller CustomControl.java.
I also have a view TestView.fxml which includes the CustomControl with a controller TestController.java. The TestView.fxml has a button. When that button is pressed it calls the method 'OnButtonPress' from the TestController.java. Now in that method I would like to call the method setText from the controller CustomControl.java.
Now I'm facing two problems.
First: I'm getting the exception 'Root hasn't been set. Use method setRoot() before load.'
Second: I don't know how to call the method setText from my custom control.
Here's the code:
TestView.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:controller="controller.TestController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1">
<children>
<fx:include source="../custom_control.fxml" fx:id="custom_control"/>
<Button onAction="#OnButtonPress" fx:id="button" layoutX="148.0" layoutY="117.0" mnemonicParsing="false" text="Button" />
</children>
</AnchorPane>
TestController.java:
package controller;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
public class TestController {
#FXML
private Button button;
#FXML
private VBox custom_control;
public TestController() {
}
#FXML
private void OnButtonPress() {
// that is the method I would like to call
custom_control.setText("This is the new text");
}
}
CustomControl.java:
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
public class CustomControl extends VBox {
#FXML private TextField textField;
public CustomControl() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("custom_control.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public void setText(String text){
textField.textProperty().set(text);
}
#FXML
protected void doSomething() {
textField.textProperty().set("The button was clicked");
}
}
CustomControl.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
<TextField fx:id="textField"/>
<Button text="Click Me" onAction="#doSomething"/>
</fx:root>
Okey so I figured out why I didn't work so I though I'd share what problems I had.
the name's of the packages have to start with a lower case letter not upper case
The names of the Classes as well as the views (FXML files) have to start with a upper case letter.
instead of <fx:include> you should use the actual tag of the control (in my case <CustomControl>) and import the FXML file
When doing all that it finally worked.
I'm trying to load my fxml file, which is fine and loaded (I have tried it with my main class). But, when I tried to set the content in the Controller, an error occurred saying:
incompatible types: java.lang.Object cannot be converted to javafx.scene.Node
at addNewCategorie.getDialogPane().setContent(fxmlLoader.load());
My Controller Class:
#FXML
private BorderPane mainBorder;
#FXML
public void handle_the_addition_of_newCategorie(){
Dialog<ButtonType> addNewCategorie = new Dialog<>();
addNewCategorie.setTitle("Add Categorie");
addNewCategorie.initOwner(mainBorder.getScene().getWindow());
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("/AddNewCategorie.fxml"));
try{
addNewCategorie.getDialogPane().setContent(fxmlLoader.load());
}catch (IOException E){
System.out.println("IOEXception : "+E.getMessage());
}
addNewCategorie.getDialogPane().getButtonTypes().add(ButtonType.CLOSE);
addNewCategorie.show();
}
My fxml file:
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<BorderPane fx:id="mainBorder" fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" style="-fx-background-color:#485460">
<center>
<HBox spacing="20" alignment="CENTER">
<Button text="Add new Categorie" style="-fx-background-color:#2ecc71; -fx-text-fill:white" onMouseClicked="#handle_the_addition_of_newCategorie"/>
</HBox>
</center>
</BorderPane>
had to change this:
addNewCategorie.getDialogPane().setContent(fxmlLoader.load());
to:
addNewCategorie.getDialogPane().setContent((Node)fxmlLoader.load());
and:
fxmlLoader.setLocation(getClass().getResource("/AddNewCategorie.fxml"));
To:
fxmlLoader.setLocation(getClass().getClassLoader().getResource("/AddNewCategorie.fxml"));
I am trying to use multiple fxml files in an application I am making, and in doing some research, I found that using Custom Controllers for the fxml files is the best approach towards doing this type of application.
I followed an Oracle Docs tutorial on "Mastering FXML" and set the root and controller as "this" in the CustomController.java file.
The problem arises when intellij discovers there is no controller specified in the fxml file for the onAction handler, while I am specifying the controller programmatically.
tester.java
package task01;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class tester extends Application
{
#Override
public void start(Stage stage) throws Exception
{
CustomController customController = new CustomController();
customController.getStylesheets().add("/task01/stylize.css");
stage.setScene(new Scene(customController,1920,1080));
stage.setTitle("Seneca ATM Program");
stage.setWidth(1920);
stage.setHeight(1080);
stage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
}
CustomContoller.java
package task01;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.fxml.*;
import javafx.scene.layout.Pane;
import java.io.IOException;
public class CustomController extends GridPane
{
#FXML
private Pane viewableContent;
#FXML
private Button vigilanteButton;
public CustomController()
{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("root.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try
{
fxmlLoader.load();
} catch (IOException exception)
{
throw new RuntimeException(exception);
}
}
#FXML
private void vigilanteAction(ActionEvent actionEvent)
{
System.out.println("Hello, World");
}
}
root.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.GridPane?>
<?import task01.MainMenuController?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.Pane?>
<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
<ImageView fitWidth="229.67" fitHeight="149.67" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.halignment="CENTER">
<Image url="/task01/logo.png"/>
</ImageView>
<Pane fx:id="viewableContent" GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.halignment="CENTER">
<MainMenuController/>
</Pane>
<Button fx:id="vigilanteButton">Vigilante</Button>
</fx:root>
MainMenuController.java
package task01;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import java.io.IOException;
public class MainMenuController extends GridPane
{
private CustomController customController = new CustomController();
public MainMenuController()
{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("mainmenu.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try
{
fxmlLoader.load();
} catch (IOException exception)
{
throw new RuntimeException(exception);
}
}
#FXML
private VBox buttonSet;
#FXML
private HBox buttonSetOne;
#FXML
private HBox buttonSetTwo;
#FXML
private Button changePinButton;
#FXML
private Button accountInquiryButton;
#FXML
private Button withdrawMoneyButton;
#FXML
private Button depositMoneyButton;
#FXML
private Button balanceInquiryButton;
#FXML
private Button createAccountButton;
#FXML
private GridPane gridpane;
#FXML
public void createAccountAction(ActionEvent actionEvent)
{
}
}
mainmenu.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<GridPane fx:id="gridpane" alignment="CENTER" vgap="50" hgap="50" xmlns:fx="http://javafx.com/fxml">
<padding><Insets top="10" bottom="10" left="10" right="10"/></padding>
<VBox fx:id="buttonSet" spacing="25" GridPane.columnIndex="0" GridPane.rowIndex="1">
<HBox fx:id="buttonSetOne" spacing="25">
<Button styleClass="menuButton" fx:id="createAccountButton" onAction="#createAccountAction">Create account</Button>
<Button styleClass="menuButton" fx:id="changePinButton">Change PIN</Button>
<Button styleClass="menuButton" fx:id="accountInquiryButton">Account Inquiry</Button>
</HBox>
<HBox fx:id="buttonSetTwo" spacing="25">
<Button styleClass="menuButton" fx:id="withdrawMoneyButton">Withdraw Money</Button>
<Button styleClass="menuButton" fx:id="depositMoneyButton">Deposit Money</Button>
<Button styleClass="menuButton" fx:id="balanceInquiryButton">Balance Inquiry</Button>
</HBox>
</VBox>
</GridPane>
Here's the problem, you can bind a FXML file to a Controller from the controller, but when you do this the IDE doesn't know it until it's up and running. That's why the IDE causes you troubles. If you want to set the onAction handler you'll have to do it from the controller. You have to create a method like this and add the onAction listener to the button:
#FXML
public void initialize() {
createAccountButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// TODO Auto-generated method stub
createAccountAction(event);
}
});
}
Divide and conquer: break complex problems to smaller ones. Start with a simple setup like the following.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class tester extends Application
{
#Override
public void start(Stage stage) throws Exception
{
CustomController customController = new CustomController();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("root.fxml"));
fxmlLoader.setController(customController);
Parent root = (Parent)fxmlLoader.load();
stage.setScene(new Scene(root,1920,1080));
stage.setTitle("Seneca ATM Program");
stage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
}
//controller should be just that. It is not a pane
class CustomController /* extends GridPane */
{
#FXML
private Pane viewableContent;
#FXML
private Button vigilanteButton;
#FXML
private void vigilanteAction(ActionEvent actionEvent)
{
System.out.println("Hello, World");
}
}
root.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.GridPane?>
<!-- ?import task01.MainMenuController?-->
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.Pane?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
<ImageView fitWidth="229.67" fitHeight="149.67" GridPane.columnIndex="0" GridPane.rowIndex="0"
GridPane.halignment="CENTER">
<Image url="task01/logo.png"/> <!-- todo: set correct path -->
</ImageView>
<Button fx:id="vigilanteButton" onAction="#vigilanteAction">Vigilante</Button>
</GridPane>
I hope this helps you to structure your application.
There's no way for the IDE to know about you setting the controller yourself somewhere in your java code. Autocompletion features and the like are off for this reason. The fact that the IDE shows these kind of "issues" is unfortunate in this case, but they could indicate an issue that can only be recognized at runtime.
In your case assuming you don't have any typos in your fxml, it's safe to ignore these warnings.
You could of course simply add the fx:controller attribute temporarily while editing the fxml and remove it when you're done.
Another way of dealing with this issue would be specifying the fx:controller attribute in the fxml and setting the controllerFactory property instead of the controller property for the loader. I don't really like this approach though:
<GridPane fx:id="gridpane" alignment="CENTER" vgap="50" hgap="50" xmlns:fx="http://javafx.com/fxml" fx:controller="task01.MainMenuController">
...
public MainMenuController() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("mainmenu.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setControllerFactory(clazz -> {
if (!clazz.isInstance(this)) {
throw new IllegalArgumentException(String.format("class of controller (%s) not assignable to class specified in fxml (%s)", this.getClass().getName(), clazz.getName()));
}
return this;
});
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
If you don't want to check assignment compatibility between the controller type specified in the fxml and the type of the controller you specify, the controllerFactory could be simplified to clazz -> this.
If you want to use this approach for multiple classes I strongly recommend creating a class for the controller factory to avoid repetitions, assuming you want to do the check...
I am learning javafx and now I am trying to apply the techniques I learnt in my java applications. My program is called "WhatsTheTime" which is a simple program which consists of an AnchorPane with an Image of a clock in it. When the pane is clicked, it is supposed to set the text of the label behind the ImageView with the current time and the clock image is set to be invisible. When I try to run the application, I get a runtimeException in the loader.load() statement. While searching on the internet, I found that it is mostly due to incorrectly specifying the fileName, but I checked the fileName and it is absolutely correct.
This is my fxml code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<fx:root type = "AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity" onMouseClicked="#getTheTime" prefHeight="198.0" prefWidth="208.0" type="AnchorPane"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="myPrototypes.WhatsTheTime">
<children>
<Rectangle arcHeight="5.0" arcWidth="5.0" height="200.0" stroke="BLACK" strokeType="INSIDE" width="208.0" />
<Label fx:id="timeLabel" layoutX="90.0" layoutY="90.0" text="Label" />
<ImageView fx:id="clockImage" fitHeight="186.0" fitWidth="193.0" layoutX="7.0" layoutY="7.0">
<image>
<Image url="#../../What'sTheTimeIcon.png" />
</image>
</ImageView>
</children>
</fx:root>
This is my Controller class:
package myPrototypes;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
public class WhatsTheTime extends AnchorPane{
#FXML
private ImageView clockImage;
#FXML
private Label timeLabel;
WhatsTheTime(){
FXMLLoader loader = new FXMLLoader
(getClass().getResource("WhatsTheTime.fxml"));
loader.setRoot(this);
loader.setController(this);
try{
loader.load();
}
catch(IOException e){
throw new RuntimeException();
}
}
#FXML
public void getTheTime(){
clockImage.setVisible(false);
SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm a");
Date date = new Date();
timeLabel.setText(timeFormat.format(date));
}
}
And this is my main class:
package myPrototypes;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class WhatsTheTimeMain extends Application {
#Override
public void start(Stage primaryStage) {
WhatsTheTime component = new WhatsTheTime();
Scene scene = new Scene(component);
primaryStage.setScene(scene);
primaryStage.sizeToScene();
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Please help me solve this problem. Tell me if you need any other information
If you specify a controller class in the FXML via the fx:controller attribute, you are instructing the FXMLLoader to instantiate that class during the load() process, and use the instance as the controller object.
However, in your case you are explicitly setting a controller on the loader prior to invoking load:
loader.setController(this);
Since the controller is already set when the FXML is loaded, this generates an exception. (If you read the stack trace, you will see it includes an error message along the lines of "Controller already specified".)
Remove the fx:controller attribute from the root element of the FXML:
<fx:root type = "AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity" onMouseClicked="#getTheTime" prefHeight="198.0" prefWidth="208.0"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" >
(Note: there may be other errors: this is the one that is immediately obvious. You should include the stack trace in your question for more complete answers.)
I have Label on my fxml file:
<children>
<Label fx:id="lblTest" text="Label" />
</children>
How can i change the text from "Label" to "Hello" from the main/controller java file?
I just started to learn the basics of JavaFX and i am not sure if it possible
Problem
You want to set the text on a label that is part of FXML/Controller/MainApp
Solution
Normally you have three files:
FXML-Document
FXML-Controller
Class that extends Application and overrides the start method
A little Example:
LabelText.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class LabelText extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="labeltext.FXMLDocumentController">
<children>
<Label fx:id="lblTest" layoutX="126.0" layoutY="92.0" minHeight="16" minWidth="69" />
</children>
</AnchorPane>
FXMLDocumentController.java
package labeltext;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class FXMLDocumentController {
#FXML
private Label lblTest;
#FXML
private void initialize() {
lblTest.setText("I'm a Label.");
}
}
And that's it.
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Label lblData = (Label) root.lookup("#lblTest");
if (lblData!=null) lblData.setText("bye");