Graph is not showing - javafx

I have a program that inputs data into a table, computes other data, then graph it afterwards. The table and the data shows properly, but the linechart shows nothing. Im using JavaFXML application and scenebuilder.
PS: I'm new at JAVA.
CONTROLLER:
package minpro1;
//import java.net.URL;
import java.text.DecimalFormat;
//import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
//import javafx.fxml.Initializable;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
public class minpro1Controller {
double s1, s2, s3, s4, s5, s6, s7, s8, s9, w1, w2, w3, w4, w5, w6, w7, w8, pan, wp1, wp2, wp3, wp4, wp5, wp6, wp7, wp8,wp9, p80, totalweight, wptotal;
double os1, os2, os3, os4, os5, os6, os7, os8, os9, us1, us2, us3, us4, us5, us6, us7, us8, us9;
XYChart.Series graph = new XYChart.Series();
#FXML
private TextField P80;
#FXML
private TextField S3;
#FXML
private TextField W7;
#FXML
private TextField S4;
#FXML
private TextField W8;
#FXML
private TextField S5;
#FXML
private TextField S6;
#FXML
private TextField S7;
#FXML
private TextField S8;
#FXML
private TextField OS1;
#FXML
private NumberAxis yaxis;
#FXML
private TextField OS3;
#FXML
private TextField OS2;
#FXML
private TextField TOTALWEIGHT;
#FXML
private TextField OS5;
#FXML
private TextField OS4;
#FXML
private NumberAxis xaxis;
#FXML
private TextField OS7;
#FXML
private TextField US1;
#FXML
private TextField OS6;
#FXML
private TextField US3;
#FXML
private TextField OS8;
#FXML
private TextField OS9;
#FXML
private TextField US2;
#FXML
private TextField US5;
#FXML
private TextField US4;
#FXML
private TextField US7;
#FXML
private TextField US6;
#FXML
private TextField US8;
#FXML
private TextField US9;
#FXML
private TextField TOTALWP;
#FXML
private TextField WP2;
#FXML
private TextField WP1;
#FXML
private TextField W1;
#FXML
private TextField WP4;
#FXML
private TextField W2;
#FXML
private TextField WP3;
#FXML
private TextField W3;
#FXML
private TextField WP6;
#FXML
private TextField PAN;
#FXML
private TextField W4;
#FXML
private TextField WP5;
#FXML
private TextField S1;
#FXML
private TextField W5;
#FXML
private TextField WP8;
#FXML
private TextField WP9;
#FXML
private TextField S2;
#FXML
private TextField W6;
#FXML
private TextField WP7;
#FXML
private LineChart<Number,Number> GRAPH;
#FXML
private Button BUTTON;
#FXML
void handleButtonAction(ActionEvent event)
{
s1 = Double.parseDouble(S1.getText());
s2 = Double.parseDouble(S2.getText());
s3 = Double.parseDouble(S3.getText());
s4 = Double.parseDouble(S4.getText());
s5 = Double.parseDouble(S5.getText());
s6 = Double.parseDouble(S6.getText());
s7 = Double.parseDouble(S7.getText());
s8 = Double.parseDouble(S8.getText());
s9 = -37;
w1 = Double.parseDouble(W1.getText());
w2 = Double.parseDouble(W2.getText());
w3 = Double.parseDouble(W3.getText());
w4 = Double.parseDouble(W4.getText());
w5 = Double.parseDouble(W5.getText());
w6 = Double.parseDouble(W6.getText());
w7 = Double.parseDouble(W7.getText());
w8 = Double.parseDouble(W8.getText());
pan = Double.parseDouble(PAN.getText());
double s[]={s9, s8, s7, s6, s5, s4, s3, s2, s1};
double w[]={pan, w1, w2, w3, w4, w5, w6, w7, w8};
totalweight=totalweightcalculations(w, pan);
wp1=(w1/totalweight)*100;
wp2=(w2/totalweight)*100;
wp3=(w3/totalweight)*100;
wp4=(w4/totalweight)*100;
wp5=(w5/totalweight)*100;
wp6=(w6/totalweight)*100;
wp7=(w7/totalweight)*100;
wp8=(w8/totalweight)*100;
wp9=(pan/totalweight)*100;
wptotal=wp1+wp2+wp3+wp4+wp5+wp6+wp7+wp8+wp9;
os1=wp1;
os2=wp2+os1;
os3=wp3+os2;
os4=wp4+os3;
os5=wp5+os4;
os6=wp6+os5;
os7=wp7+os6;
os8=wp8+os7;
os9=wp9+os8;
us1=100-os1;
us2=100-os2;
us3=100-os3;
us4=100-os4;
us5=100-os5;
us6=100-os6;
us7=100-os7;
us8=100-os8;
us9=100-os9;
double us[]={us9, us8, us7, us6, us5, us4, us3, us2, us1};
double a, b, c, d;
for(int i=0; i<9; i++)
{
if (us[i]<80 && us[i+1]>80)
{
a=Math.log10(us[i])-Math.log10(80);
b=Math.log10(us[i+1])-Math.log10(us[i]);
c=Math.log10(s[i+1])-Math.log10(s[i]);
d=Math.log10(s[i])-(c*(a/b));
p80=Math.pow(10, d);
break;
}
}
DecimalFormat df = new DecimalFormat("#.##");
String TW = df.format(totalweight);
TOTALWEIGHT.setText(TW);
String wpa = df.format(wp1);
WP1.setText(wpa);
String wpb = df.format(wp2);
WP2.setText(wpb);
String wpc = df.format(wp3);
WP3.setText(wpc);
String wpd = df.format(wp4);
WP4.setText(wpd);
String wpe = df.format(wp5);
WP5.setText(wpe);
String wpf = df.format(wp6);
WP6.setText(wpf);
String wpg = df.format(wp7);
WP7.setText(wpg);
String wph = df.format(wp8);
WP8.setText(wph);
String wpi = df.format(wp9);
WP9.setText(wpi);
String twp = df.format(wptotal);
TOTALWP.setText(twp);
String osa = df.format(os1);
OS1.setText(osa);
String osb = df.format(os2);
OS2.setText(osb);
String osc = df.format(os3);
OS3.setText(osc);
String osd = df.format(os4);
OS4.setText(osd);
String ose = df.format(os5);
OS5.setText(ose);
String osf = df.format(os6);
OS6.setText(osf);
String osg = df.format(os7);
OS7.setText(osg);
String osh = df.format(os8);
OS8.setText(osh);
String osi = df.format(os9);
OS9.setText(osi);
String usa = df.format(us1);
US1.setText(usa);
String usb = df.format(us2);
US2.setText(usb);
String usc = df.format(us3);
US3.setText(usc);
String usd = df.format(us4);
US4.setText(usd);
String use = df.format(us5);
US5.setText(use);
String usf = df.format(us6);
US6.setText(usf);
String usg = df.format(us7);
US7.setText(usg);
String ush = df.format(us8);
US8.setText(ush);
String usi = df.format(us9);
US9.setText(usi);
String pp = df.format(p80);
P80.setText(pp);
for(int i=0; i<9; i++)
{
graph.getData().add(new XYChart.Data(Math.log10(s[i]), Math.log10(us[i])));
}
GRAPH.getData().add(graph);
}
private double totalweightcalculations(double[] s, double pan)
{
double a=0, tw=0;
for(int i=0; i<9;i++)
{
tw=s[i]+a;
a=tw;
}
return tw;
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.chart.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="386.0" prefWidth="1162.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="minpro1.minpro1Controller">
<children>
<Label alignment="CENTER" layoutX="25.0" layoutY="21.0" text="Size (microns)" textAlignment="CENTER" />
<Label alignment="CENTER" layoutX="144.0" layoutY="21.0" text="Weight" />
<Label alignment="CENTER" contentDisplay="CENTER" layoutX="481.0" layoutY="21.0" text="Percent Undersize" />
<Label alignment="CENTER" layoutX="357.0" layoutY="21.0" text="Percent Oversize" />
<Label alignment="CENTER" contentDisplay="CENTER" layoutX="234.0" layoutY="21.0" text="Weight Percent" />
<TextField fx:id="S1" alignment="CENTER" layoutX="25.0" layoutY="38.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="S2" alignment="CENTER" layoutX="25.0" layoutY="63.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="S3" alignment="CENTER" layoutX="25.0" layoutY="88.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="S4" alignment="CENTER" layoutX="25.0" layoutY="113.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="S5" alignment="CENTER" layoutX="25.0" layoutY="138.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="S6" alignment="CENTER" layoutX="25.0" layoutY="163.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="S7" alignment="CENTER" layoutX="25.0" layoutY="189.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="S8" alignment="CENTER" layoutX="25.0" layoutY="214.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="W8" alignment="CENTER" layoutX="127.0" layoutY="214.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="W7" alignment="CENTER" layoutX="127.0" layoutY="189.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="W6" alignment="CENTER" layoutX="127.0" layoutY="163.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="W5" alignment="CENTER" layoutX="127.0" layoutY="138.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="W4" alignment="CENTER" layoutX="127.0" layoutY="113.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="W3" alignment="CENTER" layoutX="127.0" layoutY="88.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="W2" alignment="CENTER" layoutX="127.0" layoutY="63.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="W1" alignment="CENTER" layoutX="127.0" layoutY="38.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="WP1" alignment="CENTER" editable="false" layoutX="224.0" layoutY="38.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="WP2" alignment="CENTER" editable="false" layoutX="224.0" layoutY="63.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="WP3" alignment="CENTER" editable="false" layoutX="224.0" layoutY="88.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="WP4" alignment="CENTER" editable="false" layoutX="224.0" layoutY="113.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="WP5" alignment="CENTER" editable="false" layoutX="224.0" layoutY="138.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="WP6" alignment="CENTER" editable="false" layoutX="224.0" layoutY="163.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="WP7" alignment="CENTER" editable="false" layoutX="224.0" layoutY="189.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="WP8" alignment="CENTER" editable="false" layoutX="224.0" layoutY="214.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS8" alignment="CENTER" editable="false" layoutX="350.0" layoutY="214.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS7" alignment="CENTER" editable="false" layoutX="350.0" layoutY="189.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS6" alignment="CENTER" editable="false" layoutX="350.0" layoutY="163.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS5" alignment="CENTER" editable="false" layoutX="350.0" layoutY="138.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS4" alignment="CENTER" editable="false" layoutX="350.0" layoutY="113.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS3" alignment="CENTER" editable="false" layoutX="350.0" layoutY="88.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS2" alignment="CENTER" editable="false" layoutX="350.0" layoutY="63.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS1" alignment="CENTER" editable="false" layoutX="350.0" layoutY="38.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US1" alignment="CENTER" editable="false" layoutX="478.0" layoutY="38.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US2" alignment="CENTER" editable="false" layoutX="478.0" layoutY="63.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US3" alignment="CENTER" editable="false" layoutX="478.0" layoutY="88.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US4" alignment="CENTER" editable="false" layoutX="478.0" layoutY="113.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US5" alignment="CENTER" editable="false" layoutX="478.0" layoutY="138.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US6" alignment="CENTER" editable="false" layoutX="478.0" layoutY="163.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US7" alignment="CENTER" editable="false" layoutX="478.0" layoutY="189.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US8" alignment="CENTER" editable="false" layoutX="478.0" layoutY="214.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="PAN" alignment="CENTER" layoutX="127.0" layoutY="239.0" prefHeight="25.0" prefWidth="74.0" />
<TextField fx:id="TOTALWEIGHT" alignment="CENTER" editable="false" layoutX="127.0" layoutY="264.0" prefHeight="25.0" prefWidth="74.0" />
<Label alignment="CENTER" layoutX="48.0" layoutY="243.0" text="PAN" />
<Label alignment="CENTER" layoutX="42.0" layoutY="268.0" text="TOTAL" />
<TextField fx:id="TOTALWP" alignment="CENTER" editable="false" layoutX="224.0" layoutY="264.0" prefHeight="25.0" prefWidth="102.0" />
<LineChart fx:id="GRAPH" layoutX="678.0" layoutY="28.0" prefHeight="331.0" prefWidth="416.0" title="GATES-GAUDIN-SCHUHMANN PLOT">
<xAxis>
<NumberAxis label="log Particle Size" side="BOTTOM" fx:id="xaxis" />
</xAxis>
<yAxis>
<NumberAxis fx:id="yaxis" label="log Cumulative Perent Passing" side="LEFT" />
</yAxis>
</LineChart>
<Button fx:id="BUTTON" alignment="CENTER" layoutX="581.0" layoutY="273.0" mnemonicParsing="false" onAction="#handleButtonAction" text="Show Answers" />
<Label layoutX="452.0" layoutY="338.0" text="P80">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<TextField fx:id="P80" alignment="CENTER" editable="false" layoutX="487.0" layoutY="335.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="OS9" alignment="CENTER" editable="false" layoutX="350.0" layoutY="239.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="US9" alignment="CENTER" editable="false" layoutX="478.0" layoutY="239.0" prefHeight="25.0" prefWidth="102.0" />
<TextField fx:id="WP9" alignment="CENTER" editable="false" layoutX="224.0" layoutY="239.0" prefHeight="25.0" prefWidth="102.0" />
</children>
</AnchorPane>
MAINAPP:
package minpro1;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MinPro1 extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("minpro1.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

One of your datapoints is giving a NaN x-value, which is causing the auto-range of the number axis to fail. You can see this if you provide a little logging in your button handling method:
for(int i=0; i<9; i++)
{
XYChart.Data<Number, Number> dataPoint = new XYChart.Data<>(Math.log10(s[i]), Math.log10(us[i]));
System.out.println("("+dataPoint.getXValue()+", "+dataPoint.getYValue()+")");
graph.getData().add(dataPoint);
}
You can fix the problem by checking the value before adding to the chart:
for(int i=0; i<9; i++)
{
XYChart.Data<Number, Number> dataPoint = new XYChart.Data<>(Math.log10(s[i]), Math.log10(us[i]));
System.out.println("("+dataPoint.getXValue()+", "+dataPoint.getYValue()+")");
if (Double.isFinite(dataPoint.getXValue().doubleValue())) {
graph.getData().add(dataPoint);
}
}

Related

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 with FXML Tableview not displaying

I've been searching all over for what I'm doing wrong but somehow I'm missing something. I've commented out and rewrote so much code that it's starting to be a mess (totally my fault) so hopefully I can find a solution.
I am using a FXML form to make a list of Attack class objects. The form pulls up, I type the required entries, hit the add attack button and the table does not populate. Here is the pertinent code:
Classes involved
public class Attack {
import javafx.beans.property.SimpleStringProperty;
public class Attack {
private final SimpleStringProperty weapon = new SimpleStringProperty("");
private final SimpleStringProperty range= new SimpleStringProperty("");
private final SimpleStringProperty damage= new SimpleStringProperty("");
private int attackBonus;
public String getRange(){return range.get();}
public String getName(){return weapon.get();}
public String getDamage(){return damage.get();}
public int getAttackBonus(){return attackBonus;}
public void setRange(String newRange){range.set(newRange);}
public void setWeapon(String newName){weapon.set(newName);}
public void setAttackBonus(int atkBonus){this.attackBonus = atkBonus;}
public void setDamage(String dmg){damage.set(dmg);}
Attack(String nameIn, int AB, String rangeIn, String damageIn){
setWeapon(nameIn);
setDamage(damageIn);
setRange(rangeIn);
setAttackBonus(AB);
};
Attack(){
this("", 0, "", "");
}
}
Controller Class
package sample;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class AddNPC{
#FXML
private Button save, addAttack;
#FXML
private TextField ac, hp, init, initBonus, fort, will, ref, weapon, attackBonus, damage;
#FXML
private RadioButton melee, touch, ranged, rangedTouch;
#FXML
private ToggleGroup range;
#FXML
private NPC monster;
#FXML
private Stage dialogStage;
#FXML
private final TableView<Attack> attackTableView = new TableView<>();
#FXML
private TableColumn<Attack, String> weaponColumn;
#FXML
private TableColumn<Attack, String> attackColumn;
#FXML
private TableColumn<Attack, String> rangeColumn;
#FXML
private TableColumn<Attack, String> damageColumn;
Dice d = new Dice(1, 3, 1);
/* #FXML
private final ObservableList<Attack> atk = FXCollections.observableArrayList();
public ObservableList<Attack> getAtk(){
return atk;
}*/
//public AddNPC(){};
#FXML
public void initialize(){
getAttack();
}
public ObservableList<Attack> getAttack(){
ObservableList<Attack> attacks = FXCollections.observableArrayList();
attacks.add(new Attack("Unarmed", 0, "melee", "1d3"));
return attacks;
}
#FXML
private void handleButtonAction(ActionEvent event){
//event for save here but not shown
if(event.getSource() == addAttack){
String weaponIn = weapon.getText();
int bonusIn = Integer.parseInt(attackBonus.getText());
String rangeIn = range.getSelectedToggle().getUserData().toString();
String damageIn = damage.getText();
Attack attack = new Attack(weaponIn, bonusIn, rangeIn, damageIn);
attackTableView.getItems().add(attack);
attackBonus.clear();
weapon.clear();
damage.clear();
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Line?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="541.0" prefWidth="453.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.AddNPC">
<children>
<TextField fx:id="name" layoutX="70.0" layoutY="74.0" prefHeight="25.0" prefWidth="127.0" promptText="Name" />
<TextField fx:id="hp" layoutX="71.0" layoutY="114.0" prefHeight="25.0" prefWidth="38.0" promptText="HP" />
<TextField fx:id="ac" layoutX="125.0" layoutY="114.0" prefHeight="25.0" prefWidth="38.0" promptText="AC" />
<TextField fx:id="init" layoutX="179.0" layoutY="114.0" prefHeight="25.0" prefWidth="68.0" promptText="Initiative" />
<TextField fx:id="initBonus" layoutX="261.0" layoutY="114.0" prefHeight="25.0" prefWidth="98.0" promptText="Initiative Bonus" />
<TextField fx:id="fort" layoutX="71.0" layoutY="153.0" prefHeight="25.0" prefWidth="38.0" promptText="Fort" />
<TextField fx:id="will" layoutX="125.0" layoutY="153.0" prefHeight="25.0" prefWidth="38.0" promptText="Will" />
<TextField fx:id="ref" layoutX="181.0" layoutY="153.0" prefHeight="25.0" prefWidth="57.0" promptText="Reflex" />
<Button fx:id="save" layoutX="202.0" layoutY="502.0" mnemonicParsing="false" onAction="#handleButtonAction" text="Save" />
<Button fx:id="addAttack" layoutX="185.0" layoutY="293.0" mnemonicParsing="false" onAction="#handleButtonAction" text="Add Attack" />
<Label layoutX="159.0" layoutY="23.0" prefHeight="35.0" prefWidth="127.0" text="NPC Editor">
<font>
<Font size="24.0" />
</font>
</Label>
<Label layoutX="222.0" layoutY="228.0" text="+" />
<TextField fx:id="weapon" layoutX="65.0" layoutY="224.0" promptText="Weapon Name" />
<TextField fx:id="attackBonus" layoutX="232.0" layoutY="224.0" prefHeight="25.0" prefWidth="47.0" promptText="Bonus" />
<TextField fx:id="damage" layoutX="292.0" layoutY="224.0" prefHeight="25.0" prefWidth="83.0" promptText="damage" />
<RadioButton fx:id="melee" contentDisplay="TOP" layoutX="69.0" layoutY="253.0" mnemonicParsing="false" prefHeight="35.0" prefWidth="75.0" selected="true" text="Melee" textAlignment="CENTER" userData="melee">
<toggleGroup>
<ToggleGroup fx:id="range" />
</toggleGroup></RadioButton>
<RadioButton fx:id="touch" layoutX="144.0" layoutY="262.0" mnemonicParsing="false" text="Touch" toggleGroup="$range" userData="touch" />
<RadioButton fx:id="ranged" layoutX="214.0" layoutY="262.0" mnemonicParsing="false" text="Range" toggleGroup="$range" userData="ranged" />
<RadioButton fx:id="rangedTouch" layoutX="279.0" layoutY="262.0" mnemonicParsing="false" text="Ranged Touch" toggleGroup="$range" userData="rangedTouch" />
<Line endX="100.0" layoutX="222.0" layoutY="204.0" startX="-100.0" />
<TableView fx:id="attackTableView" layoutX="18.0" layoutY="332.0" prefHeight="154.0" prefWidth="418.0">
<columns>
<TableColumn fx:id="weaponColumn" prefWidth="107.0" text="Weapon">
<cellValueFactory>
<PropertyValueFactory property="weapon" /></cellValueFactory>
</TableColumn>
<TableColumn fx:id="attackColumn" prefWidth="69.0" text="Atk Bonus">
<cellValueFactory>
<PropertyValueFactory property="attackBonus" /></cellValueFactory>
</TableColumn>
<TableColumn fx:id="rangeColumn" prefWidth="59.0" text="Range">
<cellValueFactory>
<PropertyValueFactory property="range" /></cellValueFactory>
</TableColumn>
<TableColumn fx:id="damageColumn" prefWidth="181.0" text="Damage">
<cellValueFactory>
<PropertyValueFactory property="damage" /></cellValueFactory>
</TableColumn>
</columns>
</TableView>
</children>
</AnchorPane>
Hopefully I'm not missing anything.

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

Table not updated with new row

I finally got the content into my table (because I've been mastering that mystery out for ages!). Now I'd like to add new Items to the list AND automatically update the table. I thought an ObservableList would do the trick but there seems to be more to it. Can you provide me with a solution?
Controller class:
package controller;
import java.lang.reflect.Constructor;
import db.ItemLijst;
import db.Klant;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import model.Item;
import model.ItemTypes;
public class SchermController {
#FXML
private TableView<Item> tblItems;
#FXML
private TableView<Klant> tblKlanten;
// #FXML
// private TableView<Uitlening> tblUitleningen;
#FXML
private Button btnItemToevoegen;
#FXML
private Button btnKlantToevoegen;
#FXML
private Button btnRegistreer;
#FXML
private ChoiceBox<ItemTypes> cbTypes;
#FXML
private ChoiceBox<Item> cbItems;
#FXML
private ChoiceBox<Klant> cbKlanten;
#FXML
private TextField tfTitel;
#FXML
private TextField tfVoornaam;
#FXML
private TextField tfAchternaam;
#FXML
private TextField tfStraat;
#FXML
private TextField tfNummer;
#FXML
private TextField tfPostcode;
#FXML
private TextField tfGemeente;
#FXML
private TableColumn<Item, String> tcID;
#FXML
private TableColumn<Item, ItemTypes> tcType;
#FXML
private TableColumn<Item, String> tcTitel;
#FXML
private TableColumn<Item, String> tcUitgeleend;
private ObservableList<Item> items = FXCollections.observableArrayList();
#FXML
private void initialize()
{
/*
* ItemLijst is a static object (or object with all static
methods). the CD, Film and Spel classes automatically add their record to
this class. Literally translated it means ItemList. I thought by making this
an ObservableList, the table would be automatically update its records
depending on a change to this variable (ItemLijst.items<Item>)?
*/
items = FXCollections.observableArrayList(ItemLijst.getItems());
tcID.setCellValueFactory(new PropertyValueFactory<Item, String>("ID"));
tcType.setCellValueFactory(new PropertyValueFactory<Item, ItemTypes>("Type"));
tcTitel.setCellValueFactory(new PropertyValueFactory<Item, String>("Titel"));
tcUitgeleend.setCellValueFactory(new PropertyValueFactory<Item, String>("UitgeleendString"));
tblItems.setItems(items);
// Item types
cbTypes.setItems(FXCollections.observableArrayList(ItemTypes.values()));
btnItemToevoegen.setOnAction(e -> {
try {
itemToevoegen();
} catch (Exception e1) {
System.out.println("Probleem: " + e1.getMessage());
}
});
}
/**
* This is the method which I use to add a new item to the CD, Film or Spel
class (which inherits the Item class).
*/
private void itemToevoegen() throws Exception
{
// Validatie
if (cbTypes.getValue() == null ) {
throw new Exception("Je moet een type kiezen");
} else if (tfTitel.getText().trim().isEmpty()) {
throw new Exception("Je moet een titel ingeven");
}
Class<?> klasse = Class.forName("model." + cbTypes.getValue().toString());
Constructor<?> cons = klasse.getConstructor(String.class);
cons.newInstance(tfTitel.getText());
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="438.0" prefWidth="743.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.SchermController">
<children>
<TabPane layoutX="-1.0" prefHeight="438.0" prefWidth="744.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab closable="false" text="Items">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="367.0" prefWidth="766.0">
<children>
<TableView fx:id="tblItems" layoutX="14.0" layoutY="14.0" prefHeight="343.0" prefWidth="714.0">
<columns>
<TableColumn fx:id="tcID" prefWidth="303.0" text="Item ID" />
<TableColumn fx:id="tcType" prefWidth="76.0" text="Type" />
<TableColumn fx:id="tcTitel" prefWidth="236.0" text="Titel" />
<TableColumn fx:id="tcUitgeleend" prefWidth="98.0" text="Uitgeleend" />
</columns>
</TableView>
<ChoiceBox fx:id="cbTypes" layoutX="23.0" layoutY="365.0" prefWidth="150.0" />
<TextField fx:id="tfTitel" layoutX="201.0" layoutY="365.0" prefHeight="26.0" prefWidth="352.0" promptText="Titel van item" />
<Button fx:id="btnItemToevoegen" layoutX="592.0" layoutY="365.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="131.0" text="Toevoegen" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab closable="false" text="Klanten">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TableView fx:id="tblKlanten" layoutX="14.0" layoutY="14.0" prefHeight="343.0" prefWidth="714.0">
<columns>
<TableColumn prefWidth="89.0" text="Klant ID" />
<TableColumn prefWidth="87.0" text="Voornaam" />
<TableColumn prefWidth="105.0" text="Achternaam" />
<TableColumn prefWidth="154.0" text="Straat" />
<TableColumn prefWidth="54.0" text="Nr" />
<TableColumn prefWidth="96.0" text="Postcode" />
<TableColumn prefWidth="128.0" text="Gemeente" />
</columns>
</TableView>
<TextField fx:id="tfVoornaam" layoutX="14.0" layoutY="365.0" prefHeight="26.0" prefWidth="105.0" promptText="Voornaam" />
<TextField fx:id="tfAchternaam" layoutX="125.0" layoutY="365.0" prefHeight="26.0" prefWidth="94.0" promptText="Achternaam" />
<TextField fx:id="tfStraat" layoutX="243.0" layoutY="365.0" prefHeight="26.0" prefWidth="150.0" promptText="Straat" />
<TextField fx:id="tfNummer" layoutX="396.0" layoutY="365.0" prefHeight="26.0" prefWidth="32.0" promptText="Nr" />
<TextField fx:id="tfPostcode" layoutX="431.0" layoutY="365.0" prefHeight="26.0" prefWidth="60.0" promptText="Postcode" />
<TextField fx:id="tfGemeente" layoutX="494.0" layoutY="365.0" prefHeight="26.0" prefWidth="130.0" promptText="Gemeente" />
<Button fx:id="btnKlantToevoegen" layoutX="635.0" layoutY="365.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="93.0" text="Toevoegen" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab closable="false" text="Uitleningen">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TableView fx:id="tblUitleningen" layoutX="14.0" layoutY="14.0" prefHeight="343.0" prefWidth="714.0">
<columns>
<TableColumn prefWidth="92.0" text="Klant ID" />
<TableColumn prefWidth="324.0" text="Item ID" />
<TableColumn prefWidth="155.0" text="Start Uitleen" />
<TableColumn prefWidth="142.0" text="Eind Uitleen" />
</columns>
</TableView>
<ChoiceBox fx:id="cbItems" layoutX="15.0" layoutY="364.0" prefHeight="26.0" prefWidth="185.0" />
<ChoiceBox fx:id="cbKlanten" layoutX="244.0" layoutY="364.0" prefHeight="26.0" prefWidth="203.0" />
<Button fx:id="btnRegistreer" layoutX="497.0" layoutY="364.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="229.0" text="Registreer Uitlening" />
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
Looking at the JavaDoc you will find:
public static <E> ObservableList<E> observableArrayList(Collection<? extends E> col)
Creates a new observable array list and adds a content of collection col to it.
So in fact, you are creating a new ObservableList and adding the initial items to it. The simplest solution would be to have ItemsLijst have an ObservableList, and return it in getItems. Then you should only have to do
tblItems.setItems(ItemsLijst.getItems()); // I corrected the class name

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