I want to change the labels and text in a popup FXML
window before it is shown. This is being done because all of the Help items will be very similar and I wanted to make a template FXML
and then change the values of the labels and text area accordingly to reduce coding.
I'm surprised I haven't come across a template method in JavaFX
though. If there's a better way to go about this, please do suggest it.
For the task at hand, I have the following:
@FXML
private void documentationAction(ActionEvent action) throws IOException {
Stage dialogue = new Stage();
Parent root = null;
FXMLLoader loader = new FXMLLoader();
root = loader.load(getClass().getResource("dialogues/dialogue.fxml"));
Scene scene = new Scene(root);
/*
* change text values in title (Label) and text (TextArea)
* and change the behavior of the findMore button
*/
dialogue.setTitle("Documentation");
dialogue.setScene(scene);
dialogue.show();
}
I would like to be able to change variables inside the FXM
L file, for which I've made getters
and setters
in the controller class, but I can't figure how to do this.
Is there a way? It seems like it would be necessary for changing information between windows in multi-windowed applications, so I'm sure there's something simple that I'm missing.
UPDATE Code for controller:
public class DialogueController implements Initializable {
@FXML
private Button more;
@FXML
private Button close;
@FXML
private TextArea text;
@FXML
private Label title;
public TextArea getText() {
return text;
}
public void setText(String text) {
this.text.setText(text);
}
public Label getTitle() {
return title;
}
public void setTitle(String text) {
this.title.setText(text);
}
@FXML
public void closeAction(ActionEvent action) {
// get a handle to the stage
Stage stage = (Stage) close.getScene().getWindow();
// do what you have to do
stage.close();
}
@FXML
public void moreAction(ActionEvent action) {
}
@FXML
public void makeDocumentation(ActionEvent action) {
this.title.setText("Documentation");
}
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
}
}
Full Dialogue FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" padding="$x1" prefHeight="500.0" prefWidth="400.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml" fx:controller="pdbpro.dialogues.DialogueController">
<children>
<GridPane alignment="CENTER" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label fx:id="title" alignment="CENTER_LEFT" prefWidth="-1.0" styleClass="title" text="Title" underline="false" visible="true" GridPane.columnIndex="0" GridPane.rowIndex="0">
<GridPane.margin>
<Insets fx:id="x1" />
</GridPane.margin>
</Label>
<TextArea fx:id="text" editable="false" focusTraversable="false" prefWidth="200.0" wrapText="true" GridPane.columnIndex="0" GridPane.rowIndex="1">
<GridPane.margin>
<Insets bottom="24.0" left="15.0" right="15.0" />
</GridPane.margin>
</TextArea>
<ToolBar GridPane.columnIndex="0" GridPane.rowIndex="2">
<items>
<Button fx:id="more" mnemonicParsing="false" text="Find more" />
<Button fx:id="close" mnemonicParsing="false" onAction="#closeAction" text="Close" />
</items>
<GridPane.margin>
<Insets bottom="14.0" />
</GridPane.margin>
</ToolBar>
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<padding>
<Insets fx:id="x1" />
</padding>
<rowConstraints>
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" valignment="CENTER" vgrow="NEVER" />
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="50.0" prefHeight="0.0" vgrow="ALWAYS" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</children>
<stylesheets>
<URL value="@dialogue.css" />
</stylesheets>
</AnchorPane>
Full stack trace of error at these lines
FXMLLoader loader = new FXMLLoader();
Parent root = loader.load(getClass().getResource("dialogues/dialogue.fxml"));
DialogueController dc = loader.getController();
dc.makeDocumentation(); //ERROR
Scene scene = new Scene(root);
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1440)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.control.MenuItem.fire(MenuItem.java:456)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1188)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer$6.handle(ContextMenuContent.java:1139)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer$6.handle(ContextMenuContent.java:1137)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3324)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3164)
at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3119)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1559)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2261)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:228)
at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
at com.sun.glass.ui.View.notifyMouse(View.java:922)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1435)
... 37 more
Caused by: java.lang.NullPointerException
at pdbpro.MainController.documentationAction(MainController.java:82)
... 42 more
How Does FXML Controller Work in JavaFX? We can set the controller class for the FXML document. The FXML controller class can bind the Graphical User Interface components declared within the FXML file together and also it makes the controller object becomes a mediator. We can set the controller for FXML in 2 ways:
This way the controller of the included fxml will be injected to the field with the name <fx:id value>Controller. This is a fxml containing a StackPane with a Text node. The controller for this fxml file allows getting the current counter value as well as incrementing the counter: The controller of the included fxml is injected to this controller.
JavaFX controller works based on MVC (Model-View-Controller) JavaFX MVC can be achieved by FXML (EFF-ects eXtended Markup Language). FXML is an XML based language used to develop the graphical user interfaces for JavaFX applications as in the HTML.
The controller can use them later, such as binding them to model. The controller can have an accessible initialize () method, which should take no arguments and have a return type of void. The FXML loader will call the initialize () method after the loading of the FXML document is complete.
One way I can see is to make your controller implement initializable and implement the initialize method. The initialize method will be called automatically when the controller is created by the fxml loader. When the inititialize method is called all the fxml object declared should be initialized and ready to be customized.
[edit] After reading the docs for initializable, it says that if a method called initialize with no args is created that it will be called automatically with the fxml loader. So from what I understand, you don't need to implement initializable. Just create an initialize method with no args.
If needed, further info may be found in an introduction to fxml.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With