JavaFX Render stage below parent - java

According to the JavaFX documentation, a child stage is defined by
A stage will always be on top of its parent window.
The issue is I'd like to render them like normal windows according to each other (if you click on one, it will render above the other). Can I do this without a hacky workaround?

The only other functionality you get from making a stage a child of another stage is that the child stage is automatically closed when the parent stage is closed. You can emulate this with a listener:
Stage firstStage = ... ;
Stage secondStage = new Stage();
// secondStage.initOwner(firstStage);
firstStage.addEventHandler(WindowEvent.WINDOW_HIDDEN, evt -> secondStage.hide());
// ...
If you are relying on using getOwner() anywhere you would have to find a way around that.
(I'm not sure if this qualifies as a "hacky workaround", but it should work...).

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

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.

View related commands in MVVM application

I was inspired by article Decouple the View and its behavior to create a testable UI and wanna rework my JavaFX application with MVVM pattern.
(source: s-msft.com)
.
Ideally View Model should be View-independent and be testable as usual Java class. Also MVVM uses Command conseption to change View Model from View. So Command implementation is a part of View Model implementation and may be simply tested.
The questions is how Command should be implemented if it's result is a View changing? E.g. in View_1 I have a button after pressing on it a new View (e.g. View_2) should be created and shown. Should such Command be a part of a View and not be testable at all?
I think command could be testable. I'm not sure how exactly are you going to switch views, but AFAIK in JavaFX there is something like a Scene and Stage which is parent for scenes, is that right?
So in your command you pass the Stage as a dependency and on execution you set it a new scene.
And you can easily test it in unit tests - you can mock Stage and check if command passes correct scene to it.
I don't remember exact details of JavaFX but I would implement it like this:
class SwitchSceneCommand {
protected Stage stage;
protected Scene originalScene; // you can keep original scene if you want to have some undo-redo functionality
protected Scene newScene;
public SwitchSceneCommand(Stage stage, Scene originalScene, Scene newScene)
{
this.stage = stage;
this.originalScene = originalScene;
this.newScene = newScene;
}
public void execute()
{
this.stage.setScene(this.newScene);
}
}

JavaFX Scene Builder - How can I access the components

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.

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.

Categories

Resources