JavaFX element is initialize with size 0 - css

I have a problem when my FXML are initialized and theirs values are listen by listeners.
So my main window is a BorderPane
TOP = menu.fxml
CENTER = center1.fxml
BOTTOM = footer.fxml
When I click on one of buttons on center1Controller the CENTER fxml should changed to center2.fxml.
In center2.fxml I have a Pane that should be Anchor.anchorLeft=60 and anchorTop = anchorBottom
I was created an listener :
public void addTopOffsetListener() {
this.logonWindowPane.heightProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
double y = (newValue.doubleValue() - logonForm.getHeight()) / 2;
logonForm.setLayoutY(y);
}
});
}
But one my screen is reload the logonForm is in bad place. When I debug moment the initialization getHeight() returns 0.
It is placed in correct place after resizing window.
I was trying fixed size of this element on FXML and on CSS.
Actually I was find an workaround. When I initialize a screen2Controller a I have added this line
public void initialize(URL url, ResourceBundle rb) {
this.logonForm.resize(300, 400);
}
There is my Screen2 fxml :
<AnchorPane id="logonWindowPane" fx:id="logonWindowPane" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="genealogytree.application.fxmlcontrollers.LogonWindowController">
<stylesheets>
<URL value="#../styles/application_logon.css" />
</stylesheets>
<children>
<Pane id="logonForm" fx:id="logonForm" prefHeight="400" prefWidth="300" minWidth="300" minHeight="400" styleClass="projectPane" AnchorPane.rightAnchor="60.0" />
</children>
</AnchorPane>
And the FXML of element there I put in logonForm :
<Pane styleClass="logonFXForm" prefHeight="400" prefWidth="300" minWidth="300" minHeight="400" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="genealogytree.application.fxmlcontrollers.LogonFormController">
<stylesheets>
<URL value="#../styles/application_logon.css" />
</stylesheets>
<children>
<JFXPasswordField focusColor="#1f7f6a" layoutX="38.0" layoutY="133.0" maxWidth="224.0" minWidth="224.0" prefHeight="48.0" prefWidth="224.0" promptText="Password" unFocusColor="#253930">
<font>
<Font size="14.0" />
</font>
</JFXPasswordField>
<JFXTextField focusColor="#1f7f6a" layoutX="38.0" layoutY="54.0" maxWidth="224.0" minWidth="224.0" prefHeight="48.0" prefWidth="224.0" promptText="Login" unFocusColor="#253930">
<font>
<Font size="14.0" />
</font>
</JFXTextField>
<JFXButton buttonType="RAISED" graphicTextGap="8.0" layoutX="61.0" layoutY="224.0" prefHeight="48.0" prefWidth="178.0" ripplerFill="#32ae8f" styleClass="jfxButton" text="CONNECT" textAlignment="CENTER">
<font>
<Font name="System Bold" size="18.0" />
</font>
</JFXButton>
<Hyperlink layoutX="38.0" layoutY="305.0" prefHeight="25.0" prefWidth="250.0" text="Do not have an Account ? " />
<Hyperlink layoutX="38.0" layoutY="340.0" prefHeight="25.0" prefWidth="250.0" text="Forgotten Password ? " />
</children>
</Pane>
But there is another method to resolve my problem in FXML or CSS only ?

Related

JavaFX ScrollPane and FlowPane properties to resize the FlowPane if columns overfill the ScrollPane width

I have a FlowPane wrapped in a ScrollPane. FlowPane orientation is Vertical, so it will wrap the controls. But I want to set the FlowPane to resize vertically if the columns size is greater than the width of ScrollPane. I've tried a lot of settings, both on ScrollPane and FlowPane but none of them helped me with my wish.
As an image of how I want to do is something like this:
(red contur is ScrollPane, green is FlowPane)
Containers, after the flow pane is populated, with ScrollPane's width more than two columns of controls:
How it works right now, after resizing:
How I want to do after resizing the ScrollPane:
Can this be achieved? What settings I must do to both ScrollPane and FlowPane?
Edit:
Minimal reproduction code:
hello-view.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="424.0" prefWidth="457.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.demo.HelloController">
<children>
<AnchorPane layoutX="14.0" layoutY="14.0" prefHeight="399.0" prefWidth="430.0" style="-fx-border-color: #555555;" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0">
<children>
<ScrollPane fitToHeight="true" fitToWidth="true" focusTraversable="false" hbarPolicy="NEVER" layoutX="14.0" layoutY="13.0" maxWidth="1.7976931348623157E308" prefHeight="377.0" prefWidth="404.0" style="-fx-border-color: red; -fx-border-width: 2;" AnchorPane.bottomAnchor="7.0" AnchorPane.leftAnchor="13.0" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="12.0">
<content>
<FlowPane maxWidth="1.7976931348623157E308" orientation="VERTICAL" prefHeight="363.0" prefWidth="397.0" rowValignment="TOP" style="-fx-border-color: green; -fx-border-width: 2;">
<children>
<Button mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="1">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="12.0" layoutY="12.0" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="2">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="10.0" layoutY="135.0" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="3">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="154.0" layoutY="10.0" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="4">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
</children>
</FlowPane>
</content>
</ScrollPane>
</children>
</AnchorPane>
</children>
</AnchorPane>
HelloController.java:
package com.example.demo;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class HelloController {
#FXML
private Label welcomeText;
#FXML
protected void onHelloButtonClick() {
welcomeText.setText("Welcome to JavaFX Application!");
}
}
HelloApplication.java
package com.example.demo;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
HelloApplication.java and HelloController.java are default demo files from starting project in JavaFX.
Conclusion:
Is there a combination of properties for ScrollPane and FlowPane to be able to resize the FlowPane vertically and stop resizing in the right when the control inside tries to move to create a new column (this happens when ScrollPane resize vertically)? I don't want to create those invisible columns in the right, instead grows the FlowPane vertically!
Mention: this could happens in two way
when resize form from the bottom, and the controls from the bottom of the FlowPane will move to the top, and the FlowPane will resize automatically to the right and put the controls in the hidden area of FlowPane, (and)
When you resize form horizontally and there is no more space to move the controls from the right column to the next row, so the FlowPane will not stay anchored to right and to try to create an "invisible" row (or as many as it takes to move needed controls down).
I hope I make it clear as possible.
This answer I found it myself and it works only for FlowPane containing controls with the same size.
Purpose:
Allow user to populate a FlowPane in Vertical orientation, with parent ScrollPane's scrollbars set only to vertical scrollbar visible (when needed) and the FlowPane width to fit ScrollPane's width always.
Starting from a demo project in JavaFX, this is the fxml file which contains definition for the main-view (hello-view.fxml in this case).
hello-view.fxml file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="424.0" prefWidth="457.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.demo.HelloController">
<children>
<AnchorPane layoutX="14.0" layoutY="14.0" prefHeight="399.0" prefWidth="430.0" style="-fx-border-color: #555555;" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0">
<children>
<ScrollPane fx:id="scrollPane" fitToWidth="true" focusTraversable="false" hbarPolicy="NEVER" layoutX="14.0" layoutY="13.0" maxHeight="1.7976931348623157E308" maxWidth="-Infinity" prefHeight="377.0" prefWidth="404.0" style="-fx-border-color: red; -fx-border-width: 0;" AnchorPane.bottomAnchor="7.0" AnchorPane.leftAnchor="13.0" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="12.0">
<content>
<AnchorPane fx:id="ancFlow">
<children>
<FlowPane fx:id="flowPane" orientation="VERTICAL" prefHeight="368.0" prefWidth="396.0" prefWrapLength="10.0" rowValignment="TOP" style="-fx-border-color: green; -fx-border-width: 0;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Button maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="1">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="12.0" layoutY="12.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="2">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="10.0" layoutY="135.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="3">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
<Button layoutX="154.0" layoutY="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" prefHeight="121.0" prefWidth="140.0" text="4">
<FlowPane.margin>
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
</FlowPane.margin>
<font>
<Font name="System Bold" size="24.0" />
</font>
</Button>
</children>
</FlowPane>
</children>
</AnchorPane>
</content>
</ScrollPane>
</children>
</AnchorPane>
</children>
</AnchorPane>
HelloController.java file:
package com.example.demo;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.FlowPane;
import java.net.URL;
import java.util.ResourceBundle;
public class HelloController implements Initializable {
private final long buttonWidth = 144;
private final long buttonHeight = 125;
private double columns;
private double rows;
#FXML
private AnchorPane ancFlow;
#FXML
private ScrollPane scrollPane;
#FXML
private FlowPane flowPane;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// next line was used to see how ancPane is resizing
//ancFlow.setBackground(new Background(new BackgroundFill(Color.rgb(220, 120, 120), new CornerRadii(0), new Insets(0))));
}
public void resizeFlowPaneParent(){
scrollPane.heightProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
if(scrollPane.getHeight() < buttonHeight) return;
double verticalPadding = scrollPane.getPadding().getTop() + scrollPane.getPadding().getTop();
ancFlow.setPrefWidth(scrollPane.getWidth() - (scrollPane.getWidth() - scrollPane.getViewportBounds().getWidth()));
int controls = flowPane.getChildren().size();
rows = Math.floorDiv(newValue.longValue() , buttonHeight + (long)verticalPadding);
if((long)rows == 0) return;
columns = Math.ceilDiv(controls, (long)(rows));
double matchColumns = Math.floorDiv((long)(scrollPane.getWidth()- (scrollPane.getWidth() - scrollPane.getViewportBounds().getWidth())), buttonWidth);
if (columns <= matchColumns) {
if(rows * buttonHeight - (long)verticalPadding <= scrollPane.getHeight() - verticalPadding || (rows * columns * buttonHeight ) > controls * buttonHeight )
{
ancFlow.setPrefHeight(scrollPane.getHeight()-verticalPadding);
}
else
{
ancFlow.setPrefHeight(rows * buttonHeight);
}
}
else
{
double matchRows = Math.ceilDiv(controls, (long)matchColumns);
ancFlow.setPrefHeight(matchRows * buttonHeight);
}
}
});
scrollPane.widthProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
if(newValue.longValue() - (newValue.longValue() - scrollPane.getViewportBounds().getWidth()) < buttonWidth) return;
double verticalPadding = scrollPane.getPadding().getTop() + scrollPane.getPadding().getTop();
ancFlow.setPrefWidth(newValue.longValue() - (newValue.longValue() - scrollPane.getViewportBounds().getWidth()));
int controls = flowPane.getChildren().size();
columns = Math.floorDiv(newValue.longValue() - (long)(newValue.longValue() - scrollPane.getViewportBounds().getWidth()), buttonWidth);
rows = Math.ceilDiv(controls, (long)columns);
if(rows * buttonHeight < scrollPane.getHeight())
{
ancFlow.setPrefHeight(scrollPane.getHeight()-verticalPadding);
}
else
{
ancFlow.setPrefHeight(rows * buttonHeight);
}
}
});
}
}
HelloApplication.java file:
package com.example.demo;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
((HelloController)fxmlLoader.getController()).resizeFlowPaneParent();
stage.setWidth(stage.getWidth() + 1);
stage.setHeight(stage.getHeight() + 1);
}
public static void main(String[] args) {
launch();
}
}
The approach was to wrap the FlowPane in a AnchorPane. FlowPane is anchored in AnchorPane to all bounds. The AnchorPane is wrapped in ScrollPane.
In controller I've created a public method in which I added listners to widthProperty() and heightProperty() of ScrollPane to be able to calculate the rows needed for resizing the AnchorPane, based on how many items are in FlowPane and how many columns could be made with the ScrollPane's width. This method was added because size of controls must be read after the scene is displayed, which I've done it in HelloApplication.java main class. In this way listners are added after all items are displayed, and it will be calculated correctly.
Demo:

Retrieving strings from textfields in a .fxml file when a button is clicked. (creating a login scene to switch scenes to home scene)

very new to programming. I am learning java and javaFX.
I have tried to make a login scene and a home scene and currently have a "login" button that invokes a method in the controller -loginButton()- that switches between the two scenes. The part I am unsure on is how to set up this method to retrieve the strings from the username and password text/password fields.
I am not interested just yet in setting this up with a database. what I want to go for is something like this (rubbish login details for the purpose of example, I would never actually use login info this bad):
public void loginButton(javafx.event.ActionEvent actionEvent) throws IOException {
if(textFromLoginField=="admin"){
if(textFromPasswordField=="Password123"){
//run code to change scene
}
}
}
I know how to switch scene but I dont know how to get the login info (shown as textFromLoginField and textFromPasswordField in the example above.
How I am switching scenes
Node node=(Node) actionEvent.getSource();
Stage stage=(Stage) node.getScene().getWindow();
stage.setScene(new Scene(FXMLLoader.load(getClass().getResource("homeScene.fxml")),750,500));
stage.show();
My FXML text:
VBox maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="159.0" prefWidth="157.0" spacing="10.0" style="-fx-background-color: Black;" HBox.hgrow="NEVER">
<HBox.margin>
<Insets bottom="60.0" top="60.0" />
</HBox.margin>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Label text="LOGIN:" textFill="WHITE" />
<TextField fx:id="loginTextField" promptText="Username" />
<PasswordField fx:id="passwordTextField" promptText="Password" />
<HBox alignment="TOP_RIGHT" prefHeight="21.0" prefWidth="137.0" spacing="10.0">
<children>
<Button mnemonicParsing="false" fx:id="loginbutton" onAction="#loginButton" style="-fx-background-color: Blue;" text="Login" textAlignment="CENTER" textFill="WHITE">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
<Button mnemonicParsing="false" fx:id="helpbutton" onAction="#helpButton" style="-fx-background-color: Orange;" text="Help" textAlignment="CENTER" textFill="WHITE">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
</children>
</HBox>
</children>
</VBox>
Any help greatly appreciated :)
-Also, if I have used any technical vocab incorrectly please let me know. I am new to this. thanks
"==" doesn't work with Strings. Use textFromLoginField.equals();. Check out the string functions.

gluon SceneBuilder ToggleButtonGroup doesnt include getSelectedToggle() method

I am trying to create a ToggleButton inside a ToggleGroup but the ToggleButtonGroup class that is provided in the scene builder does not include getSelectedToggle() method which will allow me to manipulate the selected toggle state. this method however, is included in the ToggleGroup class, but unfortunately the class does not exist in the scenebuilder..
Even if the ToggleGroup class is enabled it will be difficult, since it doesn't extend javafx.scene.Node...
Is there any way I can use the getSelectedToggle() method with the class ToggleButtonGroup? If not how is there a way I can get past this?
thanks in advance...
this is my code when i tried using ToggleGroup:
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="799.9999000000025" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.medicalManagement.LoginScreen.LoginScreenController">
<children>
<Pane prefHeight="800.0" prefWidth="640.0" />
<Pane layoutX="641.0" layoutY="34.0" prefHeight="800.0" prefWidth="640.0">
<children>
<Label layoutX="18.0" layoutY="168.0" prefHeight="23.0" prefWidth="114.0" text="Username">
<font>
<Font size="14.0" fx:id="x1" />
</font>
</Label>
<TextField fx:id="userName" layoutX="17.0" layoutY="213.0" prefHeight="25.0" prefWidth="171.0" />
<Label font="$x1" layoutX="264.0" layoutY="168.0" prefHeight="25.0" prefWidth="84.0" text="Password" />
<Button fx:id="login" layoutX="19.0" layoutY="372.0" mnemonicParsing="false" onAction="" prefHeight="32.0" prefWidth="171.0" text="Log In" />
<Separator layoutY="129.0" orientation="VERTICAL" prefHeight="425.0" prefWidth="0.0" />
<PasswordField id="passWord" fx:id="passWord" layoutX="238.0" layoutY="211.0" prefWidth="171.0" />
<Label fx:id="dbStatus" layoutX="501.0" layoutY="756.0" prefHeight="18.0" prefWidth="120.0" />
<ToggleGroup fx:id="userToggleGroup" toggles="adminToggle, nurseToggle">
<RadioButton fx:id="adminToggle" layoutX="37.0" layoutY="290.0" mnemonicParsing="false" text="Admin" />
<RadioButton fx:id="nurseToggle" layoutX="206.0" layoutY="290.0" mnemonicParsing="false" text="Nurse" />
</ToggleGroup>
</children>
</Pane>
</children>
</Pane>
this is the controller class code:
package com.medicalManagement.LoginScreen;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import com.gluonhq.charm.glisten.control.ToggleButtonGroup;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class LoginScreenController implements Initializable{
LoginModel loginModel = new LoginModel();
#FXML
private TextField userName;
#FXML
private PasswordField passWord;
#FXML
private Button login;
#FXML
private ToggleGroup userToggleGroup;
#FXML
private ToggleButton adminToggle;
#FXML
private ToggleButton nurseToggle;
#FXML
private Label dbStatus;
#Override
public void initialize(URL location, ResourceBundle resources) {
if (this.loginModel.isDbConnected()){
this.dbStatus.setText("connected to database");
}else {
this.dbStatus.setText("database not connected");
}
this.adminToggle.setUserData("Admin");
this.nurseToggle.setUserData("Nurse");
this.adminToggle.setToggleGroup(userToggleGroup);
this.nurseToggle.setToggleGroup(userToggleGroup);
}
public void login(){
try{
if (this.loginModel.isLogin(this.userName.getText(), this.passWord.getText(),this.userToggleGroup.getSelectedToggle().getUserData().toString())){
Stage stage = (Stage)this.login.getScene().getWindow();
stage.close();
switch (this.userToggleGroup.getSelectedToggle().getUserData().toString()){
case "Admin":
adminLogin();
break;
case "Nurse":
nurseLogin();
break;
}
}else{
System.out.println(this.userName.getText());
System.out.println(this.passWord.getText());
System.out.println(this.userToggleGroup.getSelectedToggle().getUserData().toString());
}
}catch (Exception e ){
e.printStackTrace();
System.out.println(this.userName.getText());
System.out.println(this.passWord.getText());
System.out.println(this.userToggleGroup.getSelectedToggle().getUserData().toString());
}
}
private void nurseLogin() {
}
public void adminLogin(){
}
public static void main(String[] args) {
}
}
ToggleButtonGroup does not seem to allow this. You'd need to iterate through the toggles and check for the selected one.
ToggleGroup is simply a property of Toggle that can to keep all the toggles of the group from selecting multiple toggles at once. It's not a layout but a value assigned to the toggleGroup property of the Toggles.
You can use SceneBuilder to define ToggleGroups:
Select the RadioButton
Under Properties type the fx:id for your ToggleGroup in the Toggle Group field.
For all other RadioButtons in the same ToggleGroup assign the same value to the Toggle Group property.
Or in the fxml:
...
<children>
<Label layoutX="18.0" layoutY="168.0" prefHeight="23.0" prefWidth="114.0" text="Username">
<font>
<Font size="14.0" fx:id="x1" />
</font>
</Label>
<TextField fx:id="userName" layoutX="17.0" layoutY="213.0" prefHeight="25.0" prefWidth="171.0" />
<Label font="$x1" layoutX="264.0" layoutY="168.0" prefHeight="25.0" prefWidth="84.0" text="Password" />
<Button fx:id="login" layoutX="19.0" layoutY="372.0" mnemonicParsing="false" onAction="" prefHeight="32.0" prefWidth="171.0" text="Log In" />
<Separator layoutY="129.0" orientation="VERTICAL" prefHeight="425.0" prefWidth="0.0" />
<PasswordField id="passWord" fx:id="passWord" layoutX="238.0" layoutY="211.0" prefWidth="171.0" />
<Label fx:id="dbStatus" layoutX="501.0" layoutY="756.0" prefHeight="18.0" prefWidth="120.0" />
<RadioButton fx:id="adminToggle" layoutX="37.0" layoutY="290.0" mnemonicParsing="false" text="Admin">
<toggleGroup>
<ToggleGroup fx:id="userToggleGroup"/>
</toggleGroup>
</RadioButton>
<RadioButton fx:id="nurseToggle" layoutX="206.0" layoutY="290.0" mnemonicParsing="false" text="Nurse">
<toggleGroup>
<fx:reference source="userToggleGroup"/>
</toggleGroup>
</RadioButton>
</children>
...

Javafx: Binding font size to container

I am currently working on my final year project which is to create a Sudoku game/solver. The problem I have is that I am cannot find a method of resizing font size to that of its container when using a scene framework.
I would like to have the font size of a label change to the corresponding size of the gridpane it is within. I however am finding it hard to bind the properties I need such as 'widthProperty' and 'heightProperty' to that of 'Font.font(size)'
The difference of this question to other binding questions, is that my scene framework interferes with putting the binding for controls in the initialize method of a controller. I cannot do this as all of my controllers are initialized on start up not when they are shown to the scene
Here is all my code:
Main.java
package Controller;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application {
public static String mainMenu = "Main Menu";
public static String mainMenuFXML = "/FXML/MainMenu.fxml";
public static String chooseLevel = "Level Selection";
public static String chooseLevelFXML = "/FXML/ChooseLevel.fxml";
//Global Variable to be accessed across all classes
//To be used to determine which scenes are loaded in the HashMap and also which scene has been set
public static SceneFramework mainController = new SceneFramework();
#Override
public void start(Stage primaryStage) throws Exception{
//Only the main menu scene is needed to be loaded at the start
mainController.loadScene(Main.mainMenu, Main.mainMenuFXML);
mainController.setScene(Main.mainMenu);
StackPane root = new StackPane();
root.getChildren().addAll(mainController);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
SceneFramework.java
package Controller;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.layout.StackPane;
import java.util.HashMap;
public class SceneFramework extends StackPane{
//Constructor for the class
public SceneFramework(){
//The keyword super, overrides methods from the superclass
super();
}
//This HashMap is used to hold the screens(scenes) to be used within the application
protected HashMap<String, Node> scenes = new HashMap<>();
//Adds the selected scene to the HashMap
public void addScene(String title, Node scene) {
scenes.put(title, scene);
}
//Returns the Node with the specified title for use within application
public Node getScene(String title) {
return scenes.get(title);
}
//Removes the selected scene from the framework
public boolean unloadScene(String title){
if(scenes.remove(title) == null){
System.out.println("Scene cannot be located or it doesn't exist");
return false;
} else{
return true;
}
}
public boolean loadScene(String title, String resource){
//encase code segment in try for exception handling,
// as resources are required to be found and then loaded into memory
try{
//Load FXML File
FXMLLoader loadedFXMLFile = new FXMLLoader(getClass().getResource(resource));
//Get Parent of scene
Parent loadScene = loadedFXMLFile.load();
//Get the Controller class of the parent
SetSceneParent sceneController = (loadedFXMLFile.getController());
//Method of making sure every scene knows who it's parent is
sceneController.setSceneParent(this);
//Add scene to HashMap
addScene(title, loadScene);
return true;
}catch (Exception e){
//If FXML resource can't be loaded then generate this
System.out.println("Could't load FXML file");
return false;
}
}
//Method for showing scenes
//If one scenes if wanting to be shown then it is added to the root
//If multiple scenes are wanting to be loaded then the first scene is removed and the new scene is then displayed
public boolean setScene(final String title){
//Check to see if scene can be found
if(scenes.get(title) != null) {
if(!getChildren().isEmpty()){
getChildren().remove(0);
getChildren().add(0 ,scenes.get(title));
}else{
getChildren().add(scenes.get(title));
}
return true;
} else{
System.out.println("Scene not located!!!");
return false;
}
}
}
SetSceneParent.java
package Controller;
import Controller.SceneFramework;
public interface SetSceneParent {
void setSceneParent(SceneFramework sceneParent);
}
MainMenuController.java
package Controller;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import java.net.URL;
import java.util.ResourceBundle;
public class MainMenuController implements Initializable, SetSceneParent {
#FXML
public Button playButton, optionsButton, quitButton;
#Override
public void initialize(URL location, ResourceBundle resources) {
SelectionStatus.initialize();
}
#Override
public void setSceneParent(SceneFramework sceneParent) {
//Sets the parent of the scene by using the global variable of the class SceneFramework
Main.mainController = sceneParent;
}
public void handlePlayButtonAction(){
//On clicking of the play button
//The user is taken to the level difficulty scene
Main.mainController.loadScene(Main.chooseLevel, Main.chooseLevelFXML);
Main.mainController.setScene(Main.chooseLevel);
Main.mainController.unloadScene(Main.mainMenu);
}
}
MainMenu.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="480.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller.MainMenuController">
<center>
<HBox>
<children>
<VBox alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" BorderPane.alignment="TOP_CENTER" HBox.hgrow="ALWAYS">
<children>
<Label alignment="TOP_CENTER" maxHeight="120.0" prefHeight="60.0" text="Sudoku Solver" textAlignment="CENTER" underline="true" wrapText="true" VBox.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="48.0" />
</font>
<VBox.margin>
<Insets right="10.0" />
</VBox.margin>
</Label>
<Button fx:id="playButton" maxHeight="175.0" maxWidth="1400.0" mnemonicParsing="false" onAction="#handlePlayButtonAction" prefHeight="60.0" prefWidth="300.0" text="Play" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets />
</VBox.margin>
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Region maxHeight="80.0" prefHeight="0.0" VBox.vgrow="ALWAYS" />
<Button fx:id="optionsButton" maxHeight="175.0" maxWidth="1400.0" mnemonicParsing="false" prefHeight="60.0" prefWidth="300.0" text="Options" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets />
</VBox.margin>
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
<Region maxHeight="80.0" prefHeight="0.0" VBox.vgrow="ALWAYS" />
<Button fx:id="quitButton" maxHeight="175.0" maxWidth="1400.0" mnemonicParsing="false" prefHeight="60.0" prefWidth="300.0" text="Quit" VBox.vgrow="ALWAYS">
<VBox.margin>
<Insets />
</VBox.margin>
<font>
<Font name="System Bold" size="18.0" />
</font>
</Button>
</children>
</VBox>
</children>
</HBox>
</center>
<left>
<HBox BorderPane.alignment="CENTER">
<children>
<Region maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="100.0" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</left>
<right>
<HBox BorderPane.alignment="CENTER">
<children>
<Region maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="100.0" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</right>
<bottom>
<VBox BorderPane.alignment="CENTER">
<children>
<Region prefHeight="60.0" VBox.vgrow="ALWAYS" />
</children>
</VBox>
</bottom>
</BorderPane>
ChooseLevelController.java
package Controller;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import java.net.URL;
import java.util.ResourceBundle;
public class ChooseLevelController implements Initializable, SetSceneParent {
#FXML
public Label lblLevelSelection, lblLevel1, lblLevel2, lblLevel3, lblLevel4, lblLevel5, lblLevel6, lblLevel7, lblLevel8, lblLevel9, lblLevel10; // Value injected by FXMLLoader
public Button backButton;
public GridPane gridPaneCenter;
#Override
public void initialize(URL location, ResourceBundle resources) {
//Assert code is to be used in debugging making sure references to files and their elements are correct
assert lblLevel1 != null : "fx:id=\"lblLevel1\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel2 != null : "fx:id=\"lblLevel2\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel3 != null : "fx:id=\"lblLevel3\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel4!= null : "fx:id=\"lblLevel4\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel5 != null : "fx:id=\"lblLevel5\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel6 != null : "fx:id=\"lblLevel6\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel7 != null : "fx:id=\"lblLevel7\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel8 != null : "fx:id=\"lblLevel8\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel9 != null : "fx:id=\"lblLevel9\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
assert lblLevel10 != null : "fx:id=\"lblLevel10\" was not injected: check your FXML file 'ChooseLevel.fxml'.";
}
#Override
public void setSceneParent(SceneFramework screenParent) {
//Sets the parent of the scene by using the global variable of the class SceneFramework
Main.mainController = screenParent;
}
//Logic code
#FXML
public void mouseClickedLevelLabel() {
//Load the play screen when any Label is pressed
lblLevel1.setOnMouseClicked(e -> handleLabelClick(1));
lblLevel2.setOnMouseClicked(e -> handleLabelClick(2));
lblLevel3.setOnMouseClicked(e -> handleLabelClick(3));
lblLevel4.setOnMouseClicked(e -> handleLabelClick(4));
lblLevel5.setOnMouseClicked(e -> handleLabelClick(5));
lblLevel6.setOnMouseClicked(e -> handleLabelClick(6));
lblLevel7.setOnMouseClicked(e -> handleLabelClick(7));
lblLevel8.setOnMouseClicked(e -> handleLabelClick(8));
lblLevel9.setOnMouseClicked(e -> handleLabelClick(9));
lblLevel10.setOnMouseClicked(e -> handleLabelClick(10));
}
#FXML
public void handleBackButtonAction() {
//On clicking of the back button
//The user is taken to the level difficulty scene
Main.mainController.loadScene(Main.mainMenu, Main.mainMenuFXML);
Main.mainController.setScene(Main.mainMenu);
Main.mainController.unloadScene(Main.chooseLevel);
}
}
ChooseLevel.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller.ChooseLevelController">
<center>
<VBox alignment="CENTER" BorderPane.alignment="CENTER">
<children>
<GridPane fx:id="gridPaneCenter" alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1500.0" prefHeight="242.0" prefWidth="475.0" BorderPane.alignment="CENTER" VBox.vgrow="ALWAYS">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="137.0" vgrow="ALWAYS" />
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="138.0" vgrow="ALWAYS" />
</rowConstraints>
<children>
<Label fx:id="lblLevel1" onMousePressed="#mouseClickedLevelLabel" text="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel2" onMouseClicked="#mouseClickedLevelLabel" onMousePressed="#mouseClickedLevelLabel" text="2" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel3" onMousePressed="#mouseClickedLevelLabel" text="3" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel4" onMousePressed="#mouseClickedLevelLabel" text="4" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel5" onMousePressed="#mouseClickedLevelLabel" text="5" GridPane.columnIndex="4" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel6" onMouseClicked="#mouseClickedLevelLabel" onMousePressed="#mouseClickedLevelLabel" text="6" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel7" onMousePressed="#mouseClickedLevelLabel" text="7" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel8" onMousePressed="#mouseClickedLevelLabel" text="8" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel9" onMousePressed="#mouseClickedLevelLabel" text="9" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Label fx:id="lblLevel10" onMousePressed="#mouseClickedLevelLabel" text="10" GridPane.columnIndex="4" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
</children>
</GridPane>
</children>
</VBox>
</center>
<top>
<GridPane fx:id="gridPaneTop">
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" maxWidth="207.0" minWidth="10.0" prefWidth="20.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="207.0" minWidth="10.0" prefWidth="58.0" />
<ColumnConstraints hgrow="ALWAYS" maxWidth="207.0" minWidth="10.0" prefWidth="105.0" />
<ColumnConstraints hgrow="ALWAYS" maxWidth="451.0" minWidth="10.0" prefWidth="418.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button fx:id="backButton" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#handleBackButtonAction" prefHeight="30.0" prefWidth="0.0" text="Back" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.valignment="CENTER" />
<Separator prefHeight="63.0" prefWidth="73.0" visible="false" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS" />
<Label fx:id="lblLevelSelection" text="Level Selection" underline="true" GridPane.columnIndex="3">
<font>
<Font name="System Bold" size="36.0" />
</font>
</Label>
<Separator prefHeight="63.0" prefWidth="73.0" visible="false" />
</children>
</GridPane>
</top>
<bottom>
<Region prefHeight="36.0" prefWidth="600.0" BorderPane.alignment="CENTER" />
</bottom>
<left>
<HBox>
<children>
<Region maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="50.0" BorderPane.alignment="CENTER" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</left>
<right>
<HBox>
<children>
<Region maxWidth="1.7976931348623157E308" prefHeight="300.0" prefWidth="50.0" BorderPane.alignment="CENTER" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</right>
</BorderPane>
Ok your code does not compile AGAIN. So I'll just post a minimal example:
App.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage primaryStage) {
View view = new View();
Scene scene = new Scene(view, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
View.java
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
public class View extends AnchorPane {
public View() {
GridPane gridPane = new GridPane();
ColumnConstraints column = new ColumnConstraints();
column.setPercentWidth(33.33);
column.setHalignment(HPos.CENTER);
gridPane.getColumnConstraints().addAll(column, column, column);
RowConstraints row = new RowConstraints();
row.setPercentHeight(33.33);
row.setValignment(VPos.CENTER);
gridPane.getRowConstraints().addAll(row, row, row);
gridPane.setGridLinesVisible(true);
AnchorPane.setTopAnchor(gridPane, 0.0);
AnchorPane.setBottomAnchor(gridPane, 0.0);
AnchorPane.setLeftAnchor(gridPane, 0.0);
AnchorPane.setRightAnchor(gridPane, 0.0);
for ( int i = 0 ; i < 9; i++ ) {
gridPane.add(new Label(i+1+""), i%3, i/3, 1, 1);
}
this.widthProperty().addListener( event -> {
this.setStyle("-fx-font-size: " + this.getWidth()/10);
});
this.getChildren().add(gridPane);
}
}
This is EXACTLY what i proposed on your other question...
Edit:
To change the font of the exact element you could go about it like this:
this.widthProperty().addListener( event -> {
ObservableList<Node> labelList = gridPane.getChildren();
for ( int i = 0; i < labelList.size(); i++ ) {
//labelList.get(i).setStyle("-fx-font-size: " + this.getWidth()/10);
if ( labelList.get(i).getClass().equals(Label.class) ) {
Label.class.cast(labelList.get(i)).setFont(Font.font(this.getWidth()/10));
}
}
});
Edit2:
To have the font scale with the height AND the width you could use a method such as this:
private void changeFontSize(List<Node> labelList) {
Double newFontSizeDouble = Math.hypot(this.getWidth(), this.getHeight())/10;
int newFontSizeInt = newFontSizeDouble.intValue();
for ( int i = 0; i < labelList.size(); i++ ) {
if ( labelList.get(i).getClass().equals(Label.class) ) {
Label.class.cast(labelList.get(i)).setFont(Font.font(newFontSizeInt));
}
}
}
And call it like this:
this.widthProperty().addListener( event -> changeFontSize(gridPane.getChildren()));
this.heightProperty().addListener( event -> changeFontSize(gridPane.getChildren()));
Edit3:
You can also bind them using property bindings. There's a good tutorial on youtube here:
https://www.youtube.com/watch?v=s8GomyEOA8w&index=29&list=PL6gx4Cwl9DGBzfXLWLSYVy8EbTdpGbUIG

Add elements to a Stage from a different controller

I have a MainInterface.fxml, with its own controller MainController in which a button opens a new Stage from NewCrawler.fxml with its associated controller AddCrawlerController.
It looks fine, but i need to add stuff into the MainInterface using the interface NewCrawler .
The goal is adding a new "itemCrawler" each time someone press the "Start Crawling" button in NewCrawler, like the one hardcoded in MainInterface. How Can I do that?
MainController.java
public class MainController {
#FXML private AnchorPane mainPane;
#FXML
public void addCrawlerInstance(String domain) { //TODO dynamically add itemCrawler (Like the one hardcoded in MainInterface
Button b = new Button(domain); //it is only a try to add elements from a different controller
mainPane.getChildren().add(b);
}
#FXML
private void createCrawler () throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("guifxml/NewCrawler.fxml"));
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
}
AddCrawlerController.java
public class AddCrawlerController { //ADD Button from Main Interface
#FXML private Button abortButton;
#FXML private Button addCrawlerButton;
#FXML
private void abortCurrentWindow () {
Stage currentStage = (Stage) abortButton.getScene().getWindow();
currentStage.close();
}
#FXML
private void addNewCrawler () throws Exception { //TODO ref. Maincontroller.AddCrawlerInstance
FXMLLoader loader = new FXMLLoader(getClass().getResource("guifxml/MainInterface.fxml"));
Parent root = loader.load();
String d = "prova";
MainController controller = loader.getController();
controller.addCrawlerInstance("prova");
}
}
MainInterface.fxml
<VBox fx:id="mainApp" maxWidth="600.0" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wsa.gui.MainController">
<children>
<ButtonBar maxWidth="643.0" nodeOrientation="RIGHT_TO_LEFT" prefHeight="40.0" prefWidth="643.0">
<buttons>
<Button alignment="CENTER" mnemonicParsing="false" text="Set Path" />
<Button alignment="CENTER" mnemonicParsing="false" text="Delete" />
<Button alignment="CENTER" mnemonicParsing="false" text="Stop" />
<Button alignment="CENTER" mnemonicParsing="false" text="Start" />
<Button alignment="CENTER" mnemonicParsing="false" onMouseClicked="#createCrawler" text="Add" />
</buttons>
<VBox.margin>
<Insets />
</VBox.margin>
<padding>
<Insets right="5.0" />
</padding>
</ButtonBar>
<AnchorPane fx:id="mainPane" maxHeight="-1.0" maxWidth="-1.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
<children>
<Separator layoutY="2.0" prefHeight="3.0" prefWidth="645.0" />
<Pane fx:id="itemCrawler" prefHeight="52.0" prefWidth="645.0">
<children>
<Text layoutX="44.0" layoutY="34.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Domain">
<font>
<Font size="20.0" />
</font>
</Text>
<TextField editable="false" layoutX="124.0" layoutY="13.0" prefHeight="25.0" prefWidth="319.0" text="http://www.prova.org" />
<Button alignment="CENTER" layoutX="456.0" layoutY="13.0" mnemonicParsing="false" text="Add URI" />
<Button alignment="CENTER" layoutX="528.0" layoutY="13.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="60.0" text="Explore" />
<CheckBox layoutX="14.0" layoutY="18.0" mnemonicParsing="false" prefHeight="17.0" prefWidth="17.0" />
<Separator layoutY="51.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="3.0" prefWidth="645.0" />
</children>
</Pane>
</children>
</AnchorPane>
</children>
</VBox>
NewCrawler.fxml
<AnchorPane fx:controller="wsa.gui.AddCrawlerController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextArea layoutX="119.0" layoutY="89.0" prefHeight="237.0" prefWidth="467.0" />
<Text layoutX="44.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Domain" wrappingWidth="74.13671875">
<font>
<Font size="20.0" />
</font>
</Text>
<TextField layoutX="119.0" layoutY="32.0" prefHeight="25.0" prefWidth="467.0" />
<Text layoutX="44.0" layoutY="111.0" strokeType="OUTSIDE" strokeWidth="0.0" text="URI list" textAlignment="CENTER" wrappingWidth="74.13672208786011">
<font>
<Font size="20.0" />
</font>
</Text>
<Text layoutX="119.0" layoutY="85.0" strokeType="OUTSIDE" strokeWidth="0.0" text="one URI on each line " textAlignment="CENTER" wrappingWidth="467.00000166893005" />
<Button fx:id="addCrawlerButton" layoutX="260.0" layoutY="353.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="115.0" onMouseClicked="#addNewCrawler" text="Start Crawling" />
<Button fx:id="abortButton" layoutX="118.0" layoutY="353.0" mnemonicParsing="false" onMouseClicked="#abortCurrentWindow" prefHeight="25.0" prefWidth="115.0" text="Abort" />
</children>
</AnchorPane>
MainInterface
NewCrawler
What I understand is that you need a dynamic list of itemCrawlers.
Instead of hardcoding a newCrawler, you should use a ListView with a custom CellFactory that constructs custom ListCell to represent itemCrawler.
This tutorial tells you how to do that : http://docs.oracle.com/javafx/2/ui_controls/list-view.htm
I am not 100% sure about this, so correct me if I am wrong.
In the NewCrawler's controller you load the FXML in its constructor. Then you can instantiate the NewCrawler controller and work with it as with any other object inside your MainController.

Resources