Same Stage, Different Fxml - Javafx - java

I am new to JavaFX. I have a window loaded with vertical split pane. Here left side of the split page I have couple of buttons. On Each button click I need to load separate fxml on the right side of the split pane. So here I paste screen shot to be clear.
Here as of now I am opening in separate stage, separate scene when search button is hit. Now I need to load Searcher in the right side of baselayout window. Here is some code which loads baseLayout.
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Base Layout");
BaseController.setMlTool(this);
FXMLLoader loader = new FXMLLoader(MLTool.class.getResource("view/Base.fxml"));
baseLayout = (AnchorPane) loader.load();
Scene scene = new Scene(baseLayout);
primaryStage.setScene(scene);
primaryStage.show();
}
Here is some code which loads Searcher on button click.
#FXML
private void initialize(){
System.out.println("Testing");
}
#FXML
private void handleSearchButton(){
System.out.println("Handle Button Called");
Stage search = new Stage();
FXMLLoader loader = new FXMLLoader(MLTool.class.getResource("view/Searcher.fxml"));
search.setTitle("Searcher");
try {
AnchorPane searcherPage = (AnchorPane) loader.load();
Scene scene = new Scene(searcherPage);
search.setScene(scene);
search.show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Here how do I load Searcher in BaseLayout's Rightside of split pane.
Hope my question is clear. Thanks for your help in anticipation.

You can take pane on right side and then load fxml as child node of that pane. Stage is same for all time and you can load fxml in pane.
ex: MainWindow.fxml is perent window. You can load in stage.
Parent root = FXMLLoader.load(getClass().getResource("MainWindow.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
Now in MainWindow.fxml you have split pane. Put anchorPan on right side where you want to load fxml on button click. Then add fxml as child in anchorpane.
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(fxml));
Pane cmdPane = (Pane) fxmlLoader.load();
try {
anchCmdController.getChildren().clear();
anchCmdController.getChildren().add(cmdPane);
fadeIn.playFromStart();
} catch (Exception e) {
e.printStackTrace();
}

try to listen to the button click, once its clicked use 'FXMLLoader.load' to load based on the root elenment, typecast it say panel and assign tot he content of the right side.

In Your handler method try with this:
first declare anchorpane. In fxml right pane put anchorpane with anchCmdController name.
#FXML
private AnchorPane anchCmdController;
then update your handleSearchButton event.
#FXML
private void handleSearchButton() throws IOException {
System.out.println("Handle Button Called");
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("view/Searcher.fxml"));
Pane cmdPane = (Pane) fxmlLoader.load();
try {
/* NEED TO DECLARE ANCHOR PANE" */
anchCmdController.getChildren().clear();
anchCmdController.getChildren().add(cmdPane);
} catch (Exception e) {
e.printStackTrace();
}
}

Related

Javafx how to load button animation then execute method

I need help to load first the animation of the button then execute the onAction method because when I click the button, the animation of the button is delayed... How to fix it?
here is the sample code:
public void viewStage(ActionEvent event) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Stage.fxml"));
Parent root1 = (Parent) fxmlLoader.load();
Stage stage = new Stage();
stage.getIcons().add(new Image("/img/Stage.png"));
stage.setTitle("New Stage");
stage.setScene(new Scene(root1));
stage.show();
} catch (Exception e){
System.out.println(e);
}
}

How to know is the main Scene in memory?

I create application in JavaFX with a lot of controllers and Scene.
When I start MainApp.class it creates Stage primaryStage with Scene from startPage.fxml.
There are 2 buttons located which give a choice to open firstWindow or secondWindow.
I have 2 differs way to open that Windows
First one, When I open firstWindow I go back from startPage into MainApp and init firstWindow. It looks in MainApp.class as
public void initFirstWindow() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource(fxmlFirstWindow));
rootLayout = (BorderPane) loader.load();
firstWindow controller = loader.getController();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
in FirstWindow.class
#FXML
private BorderPane root;
public Controller controller;
...
The second way, I can start my secondWindow from the startPage when I press the button as
private MainApp main;
private BorderPane rootLayout;
private Stage childrenStage;
#FXML
public void btnSecondWindowOpen(ActionEvent actionEvent) {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource(fxmlSecondWindow));
rootLayout = (BorderPane) loader.load();
SecondWindow controller = loader.getController();
Scene scene = new Scene(rootLayout);
childrenStage = main.getStage();
childrenStage.setScene(scene);
childrenStage.show();
}
And the question is which way is better and is any memory-leaks while i start first or second Window?
As I wrote I have a lot of fxml which openes after first/second buttons, so I need to know.

JavaFX child AnchorPane not showing after adding to parent AnchorPane

So I am working on building an application that is kind of like an IDE, think Eclipse or Netbeans. I want to have different zones where users can select something like a view that will show up in one of the zones. My first attempt is to add a console view to on of my zones. In my application class I create the overall UI with the following code:
public void initialize() {
try {
mainController = (MainController) replaceSceneContent("/layout/main.fxml");
}catch (Exception ex) {
Logger.getLogger(MyApplication.class.getName()).log(Level.SEVERE, null, ex);
}
}
private Initializable replaceSceneContent(String fxml) throws Exception {
FXMLLoader loader = new FXMLLoader();
InputStream in = MyApplication.class.getResourceAsStream(fxml);
loader.setBuilderFactory(new JavaFXBuilderFactory());
loader.setLocation(MyApplication.class.getResource(fxml));
AnchorPane page;
try {
page = (AnchorPane) loader.load(in);
} finally {
in.close();
}
Scene scene = new Scene(page);
stage.setScene(scene);
stage.sizeToScene();
return (Initializable) loader.getController();
}
Which results in the following UI
I would then like to add a console widget/view to the southEast quadrant of the application. This will be handled by the MainController. In theory if someone chooses the Console view it will popup in one of the quadrants, but for now I just want to load it at start up. I try to do this with the following code:
public class MainController extends AnchorPane implements Initializable{
#FXML
SplitPane west, east;
#FXML
AnchorPane northWest, southWest, northEast, southEast, applicationHeader;
#FXML
MenuBar menuBar;
Stage stage;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
try {
ConsoleWidget cw = (ConsoleWidget)loadWidget("/widget/console.fxml");
southEast.getChildren().add(cw);
} catch (Exception e) {
e.printStackTrace();
}
}
private Initializable loadWidget(String fxml) throws Exception {
FXMLLoader loader = new FXMLLoader();
InputStream in = MainController.class.getResourceAsStream(fxml);
loader.setBuilderFactory(new JavaFXBuilderFactory());
loader.setLocation(MainController.class.getResource(fxml));
AnchorPane page;
try {
page = (AnchorPane) loader.load(in);
} finally {
in.close();
}
return (Initializable) loader.getController();
}
}
This should result in the following console appearing in the south east quadrant.
Programatically this seems to work. My southEast anchor pane shows that it has 1 child in its list if you look at it, however my UI doesnt change. I need to know how to refresh my Main controller (or do whatever I need to do) to make the change show up to the user.
I have created applications before where I create an entire new scene as the user goes through different pages but I have never really done something like this where I need to update the scene after adding a node to a pane. I have tried things like stage.sizeToScene() to try to refresh it but that hasnt worked for me.
You must return AnchorPane page instead of (Initializable) loader.getController(); to be added to the southEast anchorPane.
Declaring a Controller which extends another Node, results in a controller-node, which are used for creating Custom Controls.
These controls have constructors to set the Controller and the Root node. See this example
In your case, loader.getController() returns you an AnchorPane(rather ConsoleWidget), which is not loaded from the FXML, but is an instance of the ConsoleWidget class.

javafx - init tabs (of tab pane) on startup

I'm using eclipse & scene builder.
I has defined the main window as follow:
I want to define the "Outgoing Messages" tab with X (X is calculated on run time) of elements (the elements defined at different fxml file).
When I'm creating the main window:
private Stage primaryStage;
private AnchorPane rootLayout;
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("ABC");
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("MainLayout.fxml"));
rootLayout = (AnchorPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
How can I update the "Outgoing Messages" tabs as I described above ?
Thanks
You may use the <fx:include> inside your FXML for Outgoing Messages. This will automatically load X number of fxml before loading the main FXML. After all the incude FXML's are loaded, the FXML for Outgoing Messages is prepared and shown.
Update
If you have dynamic increase/decrease in elemtents, use the initialize() of the Outgoing Messages to populate the elements inside it instead of using <fx:incude>.
Lets consider (you may have your own logic) your Outgoing Messages has a VBox which is to be filled with dynamic no of elements(BorderPane in this case) which is inside X.fxml (You may have different FXML or you can create you own control at runtime and add it) :
pubic class OutgoingMessagesController implements Initializable {
#FXML
private VBox vbox;
public void initialize(java.net.URL location, java.util.ResourceBundle resources) {
//Whatever your logic is, I am considering a dynamic number here
for(int i=0; i<dynamicNumber; i++){
BorderPane borderPane = FXMLoader.load(getClass().getResource("X.fxml"));
vbox.getChildren.add(borderPane);
}
}
}

JavaFX - how to set default active control

I've got single window JavaFX application, created from one of the JavaFX tutorial.
I'm setting new window content by following function:
private Initializable replaceSceneContent(final String fxml) throws Exception {
// wczytanie fxml
FXMLLoader loader = new FXMLLoader();
InputStream in = Main.class.getResourceAsStream(fxml);
loader.setBuilderFactory(new JavaFXBuilderFactory());
loader.setLocation(Main.class.getResource(fxml));
AnchorPane page;
try {
page = (AnchorPane) loader.load(in);
} finally {
in.close();
}
Scene scene = new Scene(page, w, h);
stage.setScene(scene);
return (Initializable) loader.getController();
}
But i want to choose one of TextFields from this fxml file to be active by default. How to do this? I've tried to call requestFocus method in controller's initialize method but it didn't work. I haven't found any suitable property in TextField class either in AnchorPane class (AnchorPane is root element of fxml controls tree).
Try wrapping your requestFocus() call with PlatForm.runlater
Platform.runLater(new Runnable() {
public void run() {
textField.requestFocus();
}
});

Categories

Resources