JavaFX Scene Builder - How can I access the components - java

I've build a Gui using the scene builder application. I've loaded it into my application but I want to add components to a VBox buried in the design. It seems that all i have access to use is the AnchorPanel that is returned from FXMLLoader.load.
Is there any way more elegant then drilling down the children tree's to get to the component i want?
Thanks.

If you need to add to the VBox from some random class:
give an fx:id to the VBox, say "vbox"
create a Controller for the view and associate it to the view in the FXML
in the Controller, add a #FXML VBox vbox; (where vbox it the same as the fx:id)
retrieve the controller from the FXMLLoader and access the VBox: controller.vbox;.
If you just need to add something to the VBox when your view is loaded, follow 1 to 3 above and add the relevant code in the initialize method of the Controller.

Related

JavaFX multiple stages

I'm new to using Java FX and was wondering if anyone could provide some answers for me on creating multiple independent stages. I'm also using Scene Builder for ActionEvents.
An example of multiple stages could be something like this:
Login page -> main stage -> other sub stages.
The way I understand is that you need a FXML loader on each controller to bring up each stage. So on my Main java class, under START method, I'll bring up a Login stage. And on my Login Controller, I'll have a method to bring up a Main Stage (i.e. once the Login button is pressed), and finally/similarly, I'll have a method under my Main Controller to bring up other sub stages, once a button to that sub stage is pressed from the Main Stage.
Is this the right way of opening new stages? Or do I have to have all the methods in one main class to open all the stages?
Thank you for any help.
no you don't need to have to have all the methods in one main class to open all the stages. you can create your new stages in other controller when they need to be built. for example in your login page, in the controller when a button is clicked And you want to go to main stage, code for the event be like:
FXMLLoader main = new FXMLLoader();
main.setLocation(getClass().getResource("adress"));
Parent mainParent = main.load();
Scene mainScene = new Scene(mainParent);
Scene currentScene = anItemOfProgram.getScene();
Stage stage = (Stage) currentScene.getWindow();
stage.setScene(mainScene);
and this is right way to create multiple stages

Parent node not accessible during Controller object's initialize() method but ok when accessed later on

I am currently quite puzzled by the behaviour of JavaFX with regards to nested FXMLs and associated Controllers and would greatly appreciate your help on this one;
This is how the code is structured:
Stage
--> Scene loaded from "Main" FXML with BorderPane as root Node and AnchorPane as 'center' Node
----> in center-AnchorPane, <fx:include> of nested "Login" FXML file (with VBox as top-Node and including a "Login" button)
------> Login controller, injected with top-Node of Login FXML file (a VBox in the Login FXML)
Then in the controller, here is what happens from my understanding:
Construction (nothing there)
FXML injection
initialize()
NOTHING?
event-driven method on login button-click
What I am trying to do:
Accessing the Login FXML's top-Node's Parent from the Login's FXML Controller via: injected_topNode_Login_VBox.getParent().blahblahblah
What doesn't work:
During the Login FXML nested controller's initialize() method, executing the above statement returns 'null'.
During the Login FXML nested controller's initialize() method, accessing the same Parent node, but from the top-down (I have a Scene-Handling class from which I can fetch the VBox's Parent node). The interesting part here is that at that time - even though it is accessed in a static way via SceneHandlerClassName.getRootNode() where getRootNode() is a static method - the Root Node element (of the outter FXML) is also returned as being 'null'..
What works:
During the Login FXML nested controller's event-driven method loginButtonClick(), executing the exact same statement returns the AnchorPane from the Main FXML scene, as expected.
In short:
Construction
FXML injection
initialize() --> Parent of Login VBox not reachable through VBox.getParent()
NOTHING?
event-driven method --> Parent of Login VBox reachable through VBox.getParent()
From my understanding, all properties should already be available at the initialize() method's runtime execution, and I don't see why getParent() would return null then...
Has someone got an answer for me, please?
Any help would be greatly appreciated! :) :)
Cheers,
Peter
PS: I did not enclose the original code as it is quite simple in nature really, and I think my problem is most probably about my conception of how JavaFX's initialize() method is working.
Edit1: Ok, I have a new finding after #Slaw 's comment:
I have tried, still in the initialize() method of the child FXML's controller, to access the parent of the top-level node in a different way (now documented in "What doesn't work").

Setting node layoutProperty() in FXML

I'm creating a UI for a project in javafx. I'm using CSS for the styles, FXML for the structure, and also .java controllers. I'm trying to make my node(s) (i.e. button, borderpane) layout bind to the scene size, so that the window can be resized and the layout stay the same. Normally if the node was defined in a jar file I would use:
button.layoutYProperty().bind((scene.heightProperty().divide(2)));
or something similar, but my nodes are defined within the FXML file.
How can I access the nodes from outside of the FXML file so that I can define the layout or how can I define the layout within the FXML file.
(I am not using and do not intend to use scene builder).
First, you should never need to do things like this. If you use layout panes you should always be able to choose a combination of layout panes and settings that automatically position the nodes as you want them. The solutions outlined below should never really be needed.
In the controller, you typically don't have direct access to the scene, so you need to listen for when the sceneProperty() is initialized on the node and act accordingly:
public class Controller {
#FXML
private Button button ;
public void initialize() {
button.sceneProperty().addListener((obs, oldScene, newScene) -> {
button.layoutYProperty().unbind();
if (newScene != null) {
button.layoutYProperty().bind(newScene.heightProperty().divide(2));
}
});
// ...
}
}
But again, the correct approach here is to choose appropriate layout panes to achieve what you want.

Creating a JavaFX TreeView using Scene Builder

I'm starting working with JavaFX and wish to use the new tree view (as you can use multiple icons to represent your data - which is what I wish to take advantage of).
I have created a basic form/scene that has a tree view and one button on it. When this button is pressed I wish to populate the treeview.
Now, all the examples ive looked at are where the form/scene is generated in code and the treeview is bound to that control....how do I have a pre designed form with Scene builder and populate it from external code?
You could use the following code in a controller class. Inside the FXML file you will need to set the FXID to selectionTreeView. Tested in JDK 8u5 and it worked.
#FXML
TreeView selectionTreeView;
#FXML
private void handleButtonAction(ActionEvent event) {
createTree();
}
public void createTree(String... rootItems) {
//create root
TreeItem<String> root = new TreeItem<>("Root");
//root.setExpanded(true);
//create child
TreeItem<String> itemChild = new TreeItem<>("Child");
itemChild.setExpanded(false);
//root is the parent of itemChild
root.getChildren().add(itemChild);
selectionTreeView.setRoot(root);
}
Set the class name (including package) on the root node of your control in scene builder. If you click on, then go to the code tab on the right it is the top field.
Now set an ID on the TreeView in your control.
Now in the controller object add a TreeView field, the variable name should be the same as what you set the TreeView ID as in scene builder. Annotate with field with #FXML.
Now when the FXML is loaded, the controller is created and the TreeView field is set.

Which ChoiceBox-Event to choose?

I placed a ChoiceBox inside an fxml with JavaFX Scene Builder.
The FXML has a controller assigned to it.
My question is: Which event do I need to register if I want to know about changed values?
onInputMethodTextChanged="#languageSelectionModified"
this does not work with the following code
public void languageSelectionModified(Event event) {
ChoiceBox<String> box = (ChoiceBox<String>) event.getSource();
System.out.println(box.getValue());
}
and this only works for the initial click (i.e. opening the list, not when selecting an item):
onMouseClicked="#languageSelectionModified"
Although the Mouse-Events would never be a good choise because of situations where the touch or keyboard is the input-method, it still proves that the System.out can be reached.
I have absolutly no idea where those things are documentated (in the default Java-API they are not)
Add a listener to your #FXML injected choicebox in your controller:
choicebox.getSelectionModel().selectedItemProperty().addListener(choiceboxSelectionChangeListener);
You can also bind to the selected item:
label.textProperty().bind(choicebox.getSelectionModel().selectedItemProperty());
Here is an example of hooking up a listener in a controller for a ComboBox defined in FXML. Logic for a ChoiceBox is pretty much identical.
You can also use FXML onAction attribute:
<ChoiceBox onAction="#languageSelectionModified" />

Categories

Resources