how to declare date value property for tableview - javafx

I need to pass the date property to the setCellValueFactory , this is the code for the seters and geters of my Persona class, what is the correct method to do that, i think i having an issue whit the correct declaration, so i need a real direction here, i need to declare some date in the java.sql.date class, do some reference? any idea?. please a little help here.
package application;
import java.time.LocalDate;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Persona {
private StringProperty nombres;
private StringProperty apellidos;
private IntegerProperty id_cliente;
private ObjectProperty <LocalDate>fechacliente;
public Persona ( String nombres, String apellidos, Integer id_cliente, Object fechacliente) {
this.nombres= new SimpleStringProperty (nombres);
this.apellidos= new SimpleStringProperty ( apellidos);
this.id_cliente=new SimpleIntegerProperty (id_cliente);
this.fechacliente= new SimpleObjectProperty<LocalDate>();
}
public Object getFecha() {
return fechacliente.get();
}
public void setFecha(Object fechacliente) {
this.fechacliente=new SimpleObjectProperty<>();
}
public String getNombres() {
return nombres.get();
}
public void setNombres(String nombres) {
this.nombres=new SimpleStringProperty (nombres);
}
public String getApellidos() {
return apellidos.get();
}
public void setApellidos(String apellidos) {
this.apellidos=new SimpleStringProperty ( apellidos);
}
public Integer getId_cliente() {
return id_cliente.get();
}
public void setid_cliente(Integer id_cliente) {
this.id_cliente=new SimpleIntegerProperty (id_cliente);
}
}
Some of Controller here that set the values to the tableview
public void initialize(URL arg0, ResourceBundle arg1) {
clienteid.setCellValueFactory(new PropertyValueFactory <Persona, Integer>("id_cliente"));
nombrescol.setCellValueFactory(new PropertyValueFactory <Persona, String>("nombres"));
apellidoscol.setCellValueFactory(new PropertyValueFactory <Persona, String>("apellidos"));
fechacli.setCellValueFactory(new PropertyValueFactory <Persona, LocalDate>("fechacliente"));
seleccionaregistros();
seleccionanombre();
seleccionapellido();
}
this is the method i am using to retrieve the data in the tableview but the date does not show
public void seleccionaregistros() {
ObservableList <Persona> data =FXCollections.observableArrayList();
Connection conn=null;{
try {
conn = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=prueba", "sa", "milkas87");
Statement mostrar=conn.createStatement();
ResultSet rs;
rs= mostrar.executeQuery("select * from cliente");
while ( rs.next() )
{
data.add(new Persona(
rs.getString("nombre"),
rs.getString("apellido"),
rs.getInt("id"),
rs.getDate(4)
));
tablacliente.setItems(data);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
The date does not show in the tableview , i need to format the date to pass that value in the tableview i think. please some orientation here be helpful.
this is my FXML Code
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="497.0" prefWidth="943.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ConexionController">
<children>
<Pane layoutY="-3.0" prefHeight="605.0" prefWidth="1084.0">
<children>
<Button fx:id="btn" layoutX="145.0" layoutY="109.0" mnemonicParsing="false" onAction="#cargarconexion" prefHeight="46.0" prefWidth="117.0" text="Prueba Conexion" />
<Button fx:id="mtn" layoutX="15.0" layoutY="183.0" mnemonicParsing="false" onAction="#cargarregistro" prefHeight="46.0" prefWidth="117.0" text="Inserta Registro" />
<Label layoutX="14.0" layoutY="279.0" prefHeight="17.0" prefWidth="105.0" text="NOMBRES" />
<Label layoutX="15.0" layoutY="327.0" prefHeight="17.0" prefWidth="79.0" text="APELLIDOS" />
<TextField fx:id="nm" layoutX="159.0" layoutY="275.0" prefHeight="25.0" prefWidth="149.0" />
<TextField fx:id="ap" layoutX="159.0" layoutY="323.0" />
<Button fx:id="lmp" layoutX="159.0" layoutY="484.0" mnemonicParsing="false" onAction="#borrarcasillatexto" prefHeight="25.0" prefWidth="150.0" text="Limpiar Texto" />
<TableView fx:id="tablacliente" layoutX="355.0" layoutY="15.0" prefHeight="383.0" prefWidth="696.0">
<columns>
<TableColumn fx:id="clienteid" prefWidth="159.0" text="ID" />
<TableColumn fx:id="nombrescol" prefWidth="159.0" text="NOMBRES" />
<TableColumn fx:id="apellidoscol" minWidth="0.0" prefWidth="169.0" text="APELLIDOS" />
<TableColumn fx:id="fechacli" prefWidth="235.0" text="FECHA DE NACIMIENTO" />
</columns>
</TableView>
<Button fx:id="mts" layoutX="15.0" layoutY="109.0" mnemonicParsing="false" onAction="#mostrartodo" prefHeight="46.0" prefWidth="117.0" text="Mostrar" />
<TextField fx:id="bq" layoutX="554.0" layoutY="417.0" prefHeight="25.0" prefWidth="149.0" />
<Button fx:id="bqd" layoutX="758.0" layoutY="417.0" mnemonicParsing="false" onAction="#buscanm" prefHeight="25.0" prefWidth="155.0" text="BUSCAR NOMBRE" />
<Button fx:id="bqape" layoutX="758.0" layoutY="458.0" mnemonicParsing="false" onAction="#buscaape" prefHeight="25.0" prefWidth="155.0" text="BUSCAR POR APELLIDO" />
<TextField fx:id="bqa" layoutX="554.0" layoutY="458.0" />
<ComboBox layoutX="159.0" layoutY="430.0" prefWidth="150.0" />
<Label layoutX="15.0" layoutY="434.0" prefHeight="17.0" prefWidth="55.0" text="GENERO" />
<MenuBar fx:id="menucombo" layoutY="3.0">
<menus>
<Menu mnemonicParsing="false" text="Agregar">
<items>
<MenuItem mnemonicParsing="false" onAction="#inicializacombo" text="Datos Cliente" />
</items>
</Menu>
</menus>
</MenuBar>
<Button fx:id="botonborrar" layoutX="758.0" layoutY="507.0" mnemonicParsing="false" onAction="#borraregistroid" prefHeight="25.0" prefWidth="155.0" text="BORRAR REGISTRO" />
<TextField fx:id="borrar" layoutX="554.0" layoutY="507.0" />
<DatePicker fx:id="mifecha" layoutX="158.0" layoutY="371.0" prefHeight="25.0" prefWidth="150.0" />
<Label layoutX="15.0" layoutY="375.0" prefHeight="17.0" prefWidth="150.0" text="FECHA DE NACIMIENTO" />
</children>
</Pane>
</children>
</AnchorPane>

You're using JavaFX properties incorrectly. A property for a JavaFX Bean needs a getter, setter (if writable), and a property getter. Also, the setter should not be creating a new property each time; it should be setting the value of the existing property.
To simplify your example, if we have a Person with a single property, name, it would look like this:
public class Person {
private final StringProperty name = new SimpleStringProperty(this, "name");
public Person(String name) {
setName(name);
}
public final void setName(String name) { // setter
this.name.set(name);
}
public final String getName() { // getter
return name.get();
}
public final StringProperty nameProperty() { // property getter
return name;
}
}
Note: You can still initialize the properties in the constructor, instead of at the field declaration, if you want.
To use the name property in a TableView or TreeTableView you would simply return it in the cellValueFactory. Example using a TableView:
TableView<Person> table = new TableView<>();
TableColumn<Person, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(features -> features.getValue().nameProperty());
table.getColumns().add(nameCol);
Another issue with your code is that you're using a raw ObjectProperty. Don't use raw types. Instead, you should be using an ObjectProperty<Date> where Date is java.sql.Date. For example:
public class Person {
private final ObjectProperty<Date> clientDate = new SimpleObjectProperty<>(this, "clientDate");
public final void setClientDate(Date clientDate) {
this.clientDate.set(clientDate);
}
public final Date getClientDate() {
return clientDate.get();
}
public final ObjectProperty<Date> clientDateProperty() {
return clientDate;
}
}
Note: It'd probably be better to use one of the java.time classes (e.g. LocalDate, OffsetDateTime, etc...).
And again, to add it to a TableView it'd look like:
TableView<Person> table = new TableView<>();
TableColumn<Person, Date> clientDateCol= new TableColumn<>("Client Date");
clientDateCol.setCellValueFactory(features -> features.getValue().clientDateProperty());
table.getColumns().add(clientDateCol);

Related

Values not getting populated in TableView [duplicate]

This question already has answers here:
Javafx PropertyValueFactory not populating Tableview
(2 answers)
Javafx tableview not showing data in all columns
(3 answers)
Closed 1 year ago.
I am using the following code to generate a TableView:
#FXML
private TableView<Customer> customerTable;
#FXML
private TableColumn<Customer, String> customerIDColumn;
#FXML
private TableColumn<Customer, String> customerNameColumn;
#FXML
private TableColumn<Customer, String> customerPhoneColumn;
#FXML
private TableColumn<Customer, String> customerAddressColumn;
#FXML
private TableColumn<Customer, String> customerPostalCodeColumn;
#FXML
private TableColumn<Customer, String> customerDivisionColumn;
#FXML
private TableColumn<Customer, String> customerCountryColumn;
ObservableList<Customer> customerOL = FXCollections.observableArrayList();
PropertyValueFactory<Customer, String> custCustomerIDFactory = new PropertyValueFactory<>("customerID");
PropertyValueFactory<Customer, String> custNameFactory = new PropertyValueFactory<>("customerName");
PropertyValueFactory<Customer, String> custPhoneFactory = new PropertyValueFactory<>("phone"); //String value "CustomerPhone" calls getCustomerPhone method
PropertyValueFactory<Customer, String> custCountryFactory = new PropertyValueFactory<>("country");
PropertyValueFactory<Customer, String> custDivisionFactory = new PropertyValueFactory<>("division");
PropertyValueFactory<Customer, String> custAddressFactory = new PropertyValueFactory<>("address");
PropertyValueFactory<Customer, String> custPostalCodeFactory = new PropertyValueFactory<>("postalCode");
customerIDColumn.setCellValueFactory(custCustomerIDFactory);
customerNameColumn.setCellValueFactory(custNameFactory);
customerPhoneColumn.setCellValueFactory(custPhoneFactory);
customerCountryColumn.setCellValueFactory(custCountryFactory);
customerDivisionColumn.setCellValueFactory(custDivisionFactory);
customerAddressColumn.setCellValueFactory(custAddressFactory);
customerPostalCodeColumn.setCellValueFactory(custPostalCodeFactory);
Customer cust = new Customer();
cust.setCustomerID(result.getInt("Customer_ID"));
cust.setCustomerName(result.getString("Customer_Name"));
cust.setCustomerPhone(result.getString("Phone"));
cust.setCustomerAddress(result.getString("Address"));
cust.setCustomerPostalCode(result.getString("Postal_Code"));
cust.setCustomerDivision(result.getString("Division"));
cust.setCustomerCountry(result.getString("Country"));
customerOL.addAll(cust);
customerTable.setItems(customerOL);
the above is a part of java code. But I think it explains what I am trying to do.
The line customerOL.addAll(cust); adds 3 customer data into the customerOL object.
The Country, Division, etc all values are getting populated properly in the object. But when the table view is generated strangely I only see the values of ID and Customer Name being populated. The rest of the values are empty as could be seen below:
I am not sure what could be causing this. Here is the FXML file corresponding to this
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="customerAddLabel" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="683.0" prefWidth="824.0"
style="-fx-background-color: silver; -fx-border-color: black; -fx-border-radius: 5;"
xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="c195.View_Controller.CustomerScreenController">
<children>
<Label alignment="TOP_CENTER" layoutX="300.0" layoutY="14.0" prefHeight="38.0" prefWidth="226.0"
style="-fx-border-color: gray; -fx-border-radius: 5;" text="Customer" textAlignment="CENTER">
<font>
<Font name="System Bold Italic" size="25.0"/>
</font>
</Label>
<AnchorPane layoutX="16.0" layoutY="102.0" prefHeight="404.0" prefWidth="363.0"
style="-fx-background-color: white;">
<children>
<TableView fx:id="customerTable" layoutY="1.0" prefHeight="403.0" prefWidth="363.0"
style="-fx-border-color: black; -fx-border-radius: 5;">
<columns>
<TableColumn fx:id="customerIDColumn" prefWidth="63.0" text="ID"/>
<TableColumn fx:id="customerNameColumn" prefWidth="175.0" text="Customer Name"/>
<TableColumn fx:id="customerPhoneColumn" prefWidth="123.0" text="Phone"/>
<TableColumn fx:id="customerAddressColumn" prefWidth="123.0" text="Address"/>
<TableColumn fx:id="customerPostalCodeColumn" prefWidth="123.0" text="Postal Code"/>
<TableColumn fx:id="customerDivisionColumn" prefWidth="123.0" text="Division"/>
<TableColumn fx:id="customerCountryColumn" prefWidth="123.0" text="Country"/>
</columns>
</TableView>
</children>
</AnchorPane>
<TitledPane alignment="CENTER" animated="false" layoutX="413.0" layoutY="100.0" prefHeight="464.0"
prefWidth="374.0" text="Customer Details">
<content>
<GridPane prefHeight="292.0" prefWidth="373.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="172.2000732421875" minWidth="10.0"
prefWidth="99.80004272460937"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="268.199951171875" minWidth="10.0"
prefWidth="253.39995727539065"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<TextField fx:id="customerCustomerIDTextField" onAction="#CustomerCustomerIDTextFieldHandler"
GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label fx:id="customerCustomerIDLabel" text="Customer ID" GridPane.rowIndex="1"/>
<Label fx:id="customerCustomerNameLabel" text="Company Name" GridPane.rowIndex="2"/>
<Label fx:id="customerAddressLabel" text="Address" GridPane.rowIndex="4"/>
<Label fx:id="customerAddress2Label" text="POC" GridPane.rowIndex="3"/>
<Label fx:id="customerCityLabel" text="City" GridPane.rowIndex="5"/>
<Label fx:id="customerCountryLabel" text="Country" GridPane.rowIndex="6"/>
<Label fx:id="customerPostalCodeLabel" text="Postal Code" GridPane.rowIndex="7"/>
<Label fx:id="customerPhoneLabel" text="Phone No." GridPane.rowIndex="8"/>
<TextField fx:id="customerCustomerNameTextField"
onAction="#CustomerCustomerNameTextFieldHandler" GridPane.columnIndex="1"
GridPane.rowIndex="2"/>
<TextField fx:id="customerAddressTextField" onAction="#CustomerAddressTextFieldHandler"
GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<TextField fx:id="customerAddress2TextField" onAction="#CustomerAddress2TextFieldHandler"
GridPane.columnIndex="1" GridPane.rowIndex="3"/>
<ComboBox fx:id="customerCityComboBox" onAction="#CustomerCityComboBoxHandler" prefHeight="26.0"
prefWidth="252.0" GridPane.columnIndex="1" GridPane.rowIndex="5"/>
<ComboBox fx:id="customerCountryComboBox" onAction="#CustomerCountryComboBoxHandler"
prefHeight="26.0" prefWidth="252.0" GridPane.columnIndex="1" GridPane.rowIndex="6"/>
<TextField fx:id="customerPostalCodeTextField" onAction="#CustomerPostalCodeTextFieldHandler"
GridPane.columnIndex="1" GridPane.rowIndex="7"/>
<TextField fx:id="customerPhoneTextField" onAction="#CustomerPhoneTextFieldHandler"
GridPane.columnIndex="1" GridPane.rowIndex="8"/>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="20.0"
GridPane.columnIndex="1">
<children>
<RadioButton fx:id="customerActiveRadioButton" mnemonicParsing="false"
onAction="#CustomerActiveRadioButtonHandler" text="Active"/>
<RadioButton fx:id="customerInactiveRadioButton" mnemonicParsing="false"
onAction="#CustomerInactiveRadioButtonHandler" text="Inactive"/>
</children>
</HBox>
</children>
</GridPane>
</content>
</TitledPane>
<ButtonBar layoutX="587.0" layoutY="564.0" prefHeight="40.0" prefWidth="200.0">
<buttons>
<Button fx:id="customerSaveButton" minWidth="66.0" mnemonicParsing="false"
onAction="#CustomerSaveButtonHandler" prefHeight="26.0" text="Save"/>
<Button fx:id="customerCancelButton" mnemonicParsing="false" onAction="#CustomerCancelButtonHandler"
text="Cancel"/>
</buttons>
</ButtonBar>
<ButtonBar layoutX="500.0" layoutY="613.0" prefHeight="40.0" prefWidth="200.0">
<buttons>
<Button fx:id="customerBackButton" mnemonicParsing="false" onAction="#CustomerBackButtonHandler"
text="Back"/>
<Button fx:id="customerAddButton" mnemonicParsing="false" onAction="#CustomerAddButtonHandler"
text="Add"/>
<Button fx:id="customerDeleteButton" mnemonicParsing="false" onAction="#CustomerDeleteButtonHandler"
text="Delete"/>
</buttons>
</ButtonBar>
<Label fx:id="customerLabel" layoutX="542.0" layoutY="52.0" prefHeight="40.0" prefWidth="90.0"
textFill="#1924e8">
<font>
<Font name="System Bold Italic" size="20.0"/>
</font>
</Label>
<Label layoutX="34.0" layoutY="517.0" prefHeight="27.0" prefWidth="327.0"
text="Click on Customer in Table to Update" textFill="#eb0c13">
<font>
<Font name="System Bold Italic" size="18.0"/>
</font>
</Label>
</children>
</AnchorPane>
I am not sure how to debug this. As the values in the ObservableList<Customer> are getting populated properly, it just doesn't appear in the TableView.
Here is the Customer class:
public class Customer {
private int customerID; //Auto incremented in database
private String customerName;
private int active;
private Date createDate;
private String createdBy;
private String address;
private String address2;
private String division;
private String postalCode;
private String phone;
private String country;
private Date lastUpdate;
private String lastUpdateBy;
public Customer() {
}
public Customer(int customerID, String customerName, int active, String address, String address2, String division, String postalCode, String phone, String country, Date lastUpdate, String lastUpdateBy) {
setCustomerID(customerID);
setCustomerName(customerName);
setCustomerActive(active);
setCustomerAddress(address);
setCustomerAddress2(address2);
setCustomerDivision(division);
setCustomerPostalCode(postalCode);
setCustomerPhone(phone);
setCustomerCountry(country);
setCustomerLastUpdate(lastUpdate);
setCustomerLastUpdateBy(lastUpdateBy);
}
public Customer(int customerID, String customerName) {
setCustomerID(customerID); //this is Auto Incremented in the database
setCustomerName(customerName);
}
public int getCustomerID() {
return customerID;
}
public String getCustomerName() {
return customerName;
}
public int getCustomerActive() {
return active;
}
public String getCustomerAddress() {
return address;
}
public String getCustomerAddress2() {
return address2;
}
public String getCustomerCity() {
return division;
}
public String getCustomerPostalCode() {
return postalCode;
}
public String getCustomerPhone() {
return phone;
}
public String getCustomerCountry() {
return country;
}
public Date getCustomerLastUpdate() {
return lastUpdate;
}
public String getCustomerLastUpdateBy() {
return lastUpdateBy;
}
public void setCustomerID(int customerID) {
this.customerID = customerID;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public void setCustomerActive(int active) {
this.active = active;
}
public void setCustomerAddress(String address) {
this.address = address;
}
public void setCustomerAddress2(String address2) {
this.address2 = address2;
}
public void setCustomerDivision(String city) {
this.division = city;
}
public void setCustomerPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public void setCustomerPhone(String phone) {
this.phone = phone;
}
public void setCustomerCountry(String country) {
this.country = country;
}
public void setCustomerLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
public void setCustomerLastUpdateBy(String lastUpdateBy) {
this.lastUpdateBy = lastUpdateBy;
}
}

Updating a JavaFX status label

I have a JavaFX program using Model/View/Controller where I want a long running model to update a status label on the view. I found people suggesting using the Timeline class to do this. I implemented it expecting that every second, the status Label would update. However, only the final status displays. What am I doing wrong?
My controller looks like:
#FXML
private Button pullApplicantsButton;
#FXML
private Label statusLabel;
#FXML
private DatePicker orientationDate;
#FXML
private Spinner numberOfApplicants;
#FXML
private void pullApplicants() throws Exception {
SelectApplicantsModel selectApplicantsModel = new SelectApplicantsModel(orientationDate.getValue() , ( int ) numberOfApplicants.getValue() , this.statusLabel);
selectApplicantsModel.process();
}
my model looks like:
public SelectApplicantsModel(LocalDate nextOrientationDate, int numberOfApplicants , Label statusLabel ) throws FileNotFoundException {
this.nextOrientationDate = nextOrientationDate;
this.numberOfApplicants = numberOfApplicants;
this.statusLabel = statusLabel;
}
public void process() throws Exception {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds( 1 ) , event -> {
statusLabel.setText( programStatus );
})
);
timeline.setCycleCount( Animation.INDEFINITE );
timeline.play();
programStatus = "starting";
changeSearchStringToIncludeOrientationDate(nextOrientationDate);
MemberClicks memberClicks = new MemberClicks();
programStatus = "retrieving profiles";
JsonArray applicantProfilesJsonArray = memberClicks.getProfiles(searchJsonArray);
programStatus = "converting profiles";
and the view looks like:
<Label text="Picks the next 30 applicants for the upcoming orientation. Applicants whose Memberclick's OrientationDate matches the next orientation date get priority, followed by those with the oldest normalized application date." wrapText="true" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0" />
<Label text="Date of next orientation:" GridPane.columnIndex="0" GridPane.rowIndex="1" />
<DatePicker fx:id="orientationDate" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label text="Number of applicants to pull:" GridPane.columnIndex="0" GridPane.rowIndex="2" />
<Spinner fx:id="numberOfApplicants" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Button fx:id="pullApplicantsButton" mnemonicParsing="false" onAction="#pullApplicants" text="Pull Applicants" GridPane.columnIndex="0" GridPane.rowIndex="4" />
<Button fx:id="closeWindowButton" mnemonicParsing="false" onAction="#closeWindow" text="Close Window" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label fx:id="statusLabel" text="" wrapText="true" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="5" />
You can use a Task for your purpose which does all the work in a background thread so that the GUI thread will not be blocked. Here is a minimal example:
Controller Class:
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class Controller {
#FXML
private Label statusLabel;
#FXML
public void handleStartBtnClick() {
MyTask myTask = new MyTask();
statusLabel.textProperty().bind(myTask.messageProperty());
new Thread(myTask).start();
}
}
MyTask Class:
package sample;
import javafx.concurrent.Task;
public class MyTask extends Task<Void> {
#Override
protected Void call() throws Exception {
updateMessage("starting");
// while (...) {
// do something:
// changeSearchStringToIncludeOrientationDate(nextOrientationDate);
// MemberClicks memberClicks = new MemberClicks();
Thread.sleep(1000); // just for demonstration purpose
// Update the status:
updateMessage("retrieving profiles");
Thread.sleep(1000);
// Do next step:
// ...
updateMessage("converting profiles");
Thread.sleep(1000);
// } End of while loop
return null;
}
#Override
protected void succeeded() {
updateMessage("succeeded");
}
}
FXML File:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Button onAction="#handleStartBtnClick" text="Start background task"/>
<Label fx:id="statusLabel" text="Status"/>
</children>
</VBox>

StringProperty and Switch Statement Javafx

My brain is about to explode. I am pretty new to java, so far self-taught but I really want to get this code to work. I am also not the best at making sense of the java docs.
I am trying to create a gameloop where the user can freely traverse the switch statement by clicking the buttons.
However, previously, when my gameloop method was called, it ran the code with the current settings without letting me use the buttons to traverse the switch statement.
I think this was because my "choice" variable did not have an action listener attached to it (because a listener will make the program sit on the item, waiting for something to happen?). Unfortunately, my choice variable was a String variable and you cannot attach an actionlistener to a String variable.
Now I tried using the StringProperty class to create a string object to be able to attach an action listener to it.
But now I don't even know how to use StringProperty with switch statement and I just feel like I am on the wrong track.
Does it make sense what I am trying to accomplish?
Can anybody help me create a gameloop where the user can freely traverse the switch statement by clicking the buttons?
♥♥♥!
Here is my code:
Controller:
package sample;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
import static java.lang.System.out;
public class Controller implements Initializable {
public String question;
public StringProperty choice = new SimpleStringProperty(this, "choice", "");
// this code starts when the XML file is loaded.
#Override
public void initialize(URL location, ResourceBundle resources) {
question = "0";
gameloop();
} public String getChoice() {
return choice.get();
}
public StringProperty choiceProperty() {
return choice;
}
public void setChoice(String choice) {
this.choice.set(choice);
}
// public String choice = "";
public Controller() {
}
// Here are the buttons trying to add an actionlistener to the choice object.
// Maybe wrong path to go
#FXML
public void button1() {
choiceProperty().addListener((v, oldValue, newValue) ->{setChoice("c1");});
}
#FXML
public void button2() {
choiceProperty().addListener((v, oldValue, newValue) ->{setChoice("c2");});
out.println(choice); //think this prints out where it is stored in the memory
}
#FXML
public void button3() {
choiceProperty().addListener((v, oldValue, newValue) ->{setChoice("c3");});
out.println(choice);
}
//this block of code does not work because of the switch (choice) statement.
//Where "c1","c2","c3" have incompatible a type error.
public void gameloop() {
switch (question) {
case "0":
switch (choice) {
case "c1":
out.println("you chose 1");
question = "1";
break;
case "c2":
out.println("you chose 2");
break;
case "c3":
out.println("you chose 3");
break;
}
case "1":
switch (choice) {
case "c1":
out.println("you chose a");
question = "0";
break;
case "c2":
out.println("you chose b");
break;
case "c3":
out.println("you chose c");
break;
}
}
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" 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="sample.Controller">
<children>
<BorderPane layoutX="163.0" layoutY="82.0" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: black;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<bottom>
<GridPane BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button fx:id="button1" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button1" onMouseClicked="#button1" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" />
<Button fx:id="button2" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button2" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" GridPane.rowIndex="1" />
<Button fx:id="button3" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button3" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" GridPane.rowIndex="2" />
</children>
</GridPane>
</bottom>
<center>
<TextArea fx:id="textArea" editable="false" prefHeight="200.0" prefWidth="200.0" promptText="..." style="-fx-border-color: grey;" wrapText="true" BorderPane.alignment="CENTER" />
</center>
<top>
<Label fx:id="label" text="Chapter 1" textFill="WHITE" BorderPane.alignment="CENTER" />
</top>
<left>
<ImageView fx:id="image1" fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
</left>
<right>
<ImageView fx:id="image2" fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
</right></BorderPane>
</children>
</AnchorPane>
Main:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 800, 500));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Registering listeners in the button event handlers is nonsense. Using listeners to modify the property they listen to is even worse. Passing a property as argument for a switch will not even compile.
In this case the smallest modification to make this work would be registering a single listener in the initialize method, calling the gameloop method from this listener and using the value stored in the property as argument for the switch.
#Override
public void initialize(URL location, ResourceBundle resources) {
question = "0";
gameloop();
choiceProperty().addListener((observable, oldValue, newValue) -> gameloop());
}
...
#FXML
private void button1() {
setChoice("c1");
}
...
public void gameloop() {
switch (question) {
case "0":
switch (choice.get()) {
...
}
...
}
}
Note however you'll get a LOT of repeated code this way. Better come up with a data structure to store the game data instead of hardcoding everything.
E.g.
public class GameData {
private final ReadOnlyObjectWrapper<Question> question;
public ReadOnlyObjectProperty<Question> questionProperty() {
return question.getReadOnlyProperty();
}
public Question getQuestion() {
return question.get();
}
private final Map<Integer, Question> questions;
public Map<Integer, Question> getQuestions() {
return questions;
}
public GameData(int initialQuestion, Map<Integer, Question> questions) {
this.questions = questions;
this.question = new ReadOnlyObjectWrapper(questions.get(initialQuestion));
}
public void activateChoice(Choice choice) {
question.set(questions.get(choice.getNextQuestion()));
}
}
public class Question {
private final String text;
public String getText() {
return text;
}
public Question(String text, Choice... choices) {
this.text = text;
this.choices = Collections.unmodifiableList(new ArrayList(Arrays.asList(choices)));
}
private final List<Choice> choices;
public List<Choice> getChoices() {
return choices;
}
}
public class Choice {
private final String text;
private final int nextQuestion;
public Choice(int nextQuestion, String text) {
this.text = text;
this.nextQuestion = nextQuestion;
}
public String getText() {
return text;
}
public int getNextQuestion() {
return nextQuestion;
}
}
public class Controller {
private GameData gameData;
#FXML
private Button button1, button2, button3;
private Button[] buttons;
#FXML
private void initialize() {
buttons = new Button[]{button1, button2, button3};
}
public void setGameData(GameData gameData) {
this.gameData = gameData;
gameData.questionProperty().addListener((observable, oldValue, newValue) -> setQuestion(newValue));
setQuestion(gameData.getQuestion());
}
private void setQuestion(Question question) {
System.out.println(question.getText());
for (Button b : buttons) {
b.setVisible(false);
}
for (int i = 0, max = Math.min(buttons.length, question.getChoices().size()); i < max; i++) {
Button b = buttons[i];
Choice c = question.getChoices().get(i);
b.setUserData(c);
b.setText(c.getText());
b.setVisible(true);
}
}
#FXML
private void button(ActionEvent evt) {
Node source = (Node) evt.getSource();
Choice choice = (Choice) source.getUserData();
out.println("You've chosen " + choice.getText());
gameData.activateChoice(choice);
}
}
...
<Button fx:id="button1" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" />
<Button fx:id="button2" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" GridPane.rowIndex="1" />
<Button fx:id="button3" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#button" style="-fx-background-color: black; -fx-border-color: grey;" text="Button" textFill="WHITE" GridPane.rowIndex="2" />
...
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
Map<Integer, Question> questions = new HashMap<>();
questions.put(0, new Question("0",
new Choice(1, "1"),
new Choice(0, "2"),
new Choice(0, "3")
));
questions.put(1, new Question("1",
new Choice(0, "a"),
new Choice(1, "b"),
new Choice(1, "c")
));
GameData data = new GameData(0, questions);
loader.<Controller>getController().setGameData(data);

Load Exception in fxml

I want my inventory_layout to load when i click on the first button but i am getting load exception there while the same code works fine with other fxmls.
Path of controller is right.
fxml is in the right place.
Here is my code- Inventory
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import pharmbooks.Utils.DbSingleton;
import pharmbooks.Utils.UIController;
import java.io.IOException;
public class MainController {
#FXML
private BorderPane borderPane;
#FXML
public void initInventory(ActionEvent actionEvent) throws IOException{
UIController<InventoryController> uiController=new UIController<InventoryController>();
uiController.setUp(borderPane,"inventory_layout.fxml");
}
public void initPurchase(ActionEvent actionEvent) throws IOException{
UIController<PurchaseController> uiController=new UIController<>();
uiController.setUp(borderPane,"purchase_layout.fxml");
}
}
Ui Controller
public class UIController<T> {
private T controller;
private Pane pane;
public T getController() {
return controller;
}
public void setUp(Pane mainPane,String fxmlLocation){
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getClassLoader().getResource(fxmlLocation));
pane = loader.load();
controller = loader.getController();
mainPane.getChildren().clear();
mainPane.getChildren().add(pane);
}catch (Exception e){
System.out.println(UIController.class.getSimpleName()+" "+e.toString());
}
} }
This code works well in ubuntu though :/
here is the error :
UIController javafx.fxml.LoadException:
/Users/manyamadan/Desktop/Everything/pharmbooks-v2/target/classes/inventory_layout.fxml
Inventory controller :
public class InventoryController implements Initializable{
public TableColumn batchId;
public TableColumn company;
public TableColumn name;
public TableColumn packing;
public TableColumn quantity;
public TableColumn expiry;
public TableColumn mrp;
#FXML
private TableView<Inventory> personTable;
public void InventoryController()
{
}
public void initialize(URL location, ResourceBundle resources) {
batchId.setCellValueFactory(new PropertyValueFactory<Inventory, String>("BATCH_ID"));
company.setCellValueFactory(new PropertyValueFactory<Inventory, String>("COMPANY"));
name.setCellValueFactory(new PropertyValueFactory<Inventory, String>("PRODUCT_NAME"));
packing.setCellValueFactory(new PropertyValueFactory<Inventory, String>("PACKING"));
quantity.setCellValueFactory(new PropertyValueFactory<Inventory, Integer>("QUANTITY"));
expiry.setCellValueFactory(new PropertyValueFactory<Inventory, String>("EXPIRY_DATE"));
mrp.setCellValueFactory(new PropertyValueFactory<Inventory, String>("MRP"));
personTable.setEditable(true);
personTable.setItems(InventoryData.getInstance().getList());
// name.setOnEditCommit(TableColumn.CellEditEvent(Inventory,String)event);
Inventory inventory_data = personTable.getSelectionModel().getSelectedItem();
System.out.println(inventory_data.getPRODUCT_NAME()+ "" + inventory_data.getBATCH_ID());
personTable.setOnKeyPressed(event -> {
TablePosition<Inventory, ?> pos = personTable.getFocusModel().getFocusedCell() ;
if (pos != null) {
AnchorPane anchorPane= null;
try {
anchorPane = FXMLLoader.load(getClass().getClassLoader().getResource("edit_inventory_data.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
Stage stage=new Stage();
stage.setTitle("Apna Dialog");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(StageManager.getInstance().getPrimaryStage());
Scene scene = new Scene(anchorPane);
stage.setScene(scene);
stage.showAndWait();
}
});
name.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Inventory, String>>() {
#Override
public void handle(TableColumn.CellEditEvent<Inventory, String> t) {
System.out.println("ON edit commit" + t);
((Inventory) t.getTableView().getItems().get(
t.getTablePosition().getRow())).setPRODUCT_NAME(t.getNewValue());
}
}
);
}
#FXML
public void addData(ActionEvent actionEvent) throws IOException {
AnchorPane anchorPane= FXMLLoader.load(getClass().getClassLoader().getResource("add_data_inventory.fxml"));
Stage stage=new Stage();
stage.setTitle("Apna Dialog");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(StageManager.getInstance().getPrimaryStage());
Scene scene = new Scene(anchorPane);
stage.setScene(scene);
stage.showAndWait();
personTable.setItems(InventoryData.getInstance().getList());
}
}
inventory_layout.fxml
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<BorderPane maxHeight="600.0" maxWidth="800.0" prefHeight="600.0" prefWidth="800.0" stylesheets="#beautify_inventory.css" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pharmbooks.controllers.InventoryController">
<center>
<TableView fx:id="personTable" prefWidth="10000.0" BorderPane.alignment="CENTER">
<columns>
<TableColumn fx:id="batchId" prefWidth="75.0" text="BatchId" />
<TableColumn fx:id="packing" prefWidth="75.0" text="packing" />
<TableColumn fx:id="quantity" prefWidth="75.0" text="quantity" />
<TableColumn fx:id="expiry" prefWidth="75.0" text="expiry" />
<TableColumn fx:id="mrp" prefWidth="75.0" text="mrp" />
</columns>
</TableView>
</center>
<top>
<HBox prefHeight="67.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<children>
<TextField prefHeight="47.0" prefWidth="163.00009155273438">
<HBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</HBox.margin>
</TextField>
<Button mnemonicParsing="false" onAction="#addData" text="Button">
<HBox.margin>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" prefHeight="39.0" prefWidth="121.0" text="Button">
<HBox.margin>
<Insets bottom="20.0" right="20.0" top="20.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" prefHeight="39.0" prefWidth="129.0" text="Button">
<HBox.margin>
<Insets bottom="20.0" top="20.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</top>
</BorderPane>
In inventory_layout.fxml you set fx:id attribute to all table columns:
<TableColumn fx:id="batchId" prefWidth="75.0" text="BatchId" />
<TableColumn fx:id="packing" prefWidth="75.0" text="packing" />
<TableColumn fx:id="quantity" prefWidth="75.0" text="quantity" />
<TableColumn fx:id="expiry" prefWidth="75.0" text="expiry" />
<TableColumn fx:id="mrp" prefWidth="75.0" text="mrp" />
but in InventoryController you does not annotate this components with #FXML. Witout this annotations FXMLLoader will not be able to inject correct objects to controller. Correct code:
#FXML
public TableColumn batchId;
#FXML
public TableColumn company;
#FXML
public TableColumn name;
#FXML
public TableColumn packing;
#FXML
public TableColumn quantity;
#FXML
public TableColumn expiry;
#FXML
public TableColumn mrp;
I'm guessing that you get NullPointerException in initalize() method when you try to setCellValueFactory() on table columns.
I assume that you are accessing fxml resource files correctly.

JavaFX, why is TableColumn null?

As you will see I am a massive noob when it comes to Java and Javafx. I have spent a lot of time reading around (various forum posts, and tuts) and trying to figure out myself where I am getting this issue but it has come to the point for me to post for feedback from someone who knows their business.
When replying, please could you take the time to also explain why something isn't working and some general pointers? Here is what I have so far (my FXML and my two classes) any pointers would be fantastic!!
My FXML;
<Pane id="myScene" fx:id="myScene" maxHeight="-Infinity" maxWidth="-Infinity" 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="sample.TestController">
<children>
<TableView id="employeesTable" fx:id="employeesTable" layoutX="131.0" layoutY="64.0" prefHeight="200.0" prefWidth="360.0">
<columns>
<TableColumn id="colFirstName" fx:id="colFirstName" prefWidth="75.0" text="First Name" />
<TableColumn id="colLastName" fx:id="colLastName" prefWidth="75.0" text="Last Name" />
<TableColumn id="colEmail" fx:id="colEmail" prefWidth="75.0" text="email" />
</columns>
</TableView>
</children>
</Pane>
Now the Employee class I have;
public class Employee {
private StringProperty firstName;
private StringProperty lastName;
private StringProperty email;
public Employee(String a, String b, String c) {
this.firstName = new SimpleStringProperty(a);
this.lastName = new SimpleStringProperty(b);
this.email = new SimpleStringProperty(c);
}
public Employee() {
}
public String getFirstName() {
return firstName.get();
}
public StringProperty firstNameProperty() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public StringProperty lastNameProperty() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public String getEmail() {
return email.get();
}
public StringProperty emailProperty() {
return email;
}
public void setEmail(String email) {
this.email.set(email);
}
}
And finally the class for my test controller is
public class TestController {
public Label login;
public TextField loginUserName;
public PasswordField loginPassword;
public TextField testOutput;
#FXML TableView<Employee> employeesTable;
#FXML TableColumn<Employee, String> colFirstName;
#FXML TableColumn<Employee, String> colLastName;
#FXML TableColumn<Employee, String> colEmail;
#FXML Pane myScene;
//public javafx.scene.control.TableView employeesTable;
private ObservableList<Employee> myData;
private MainController MainController;
public void loadEmployeeForm(ActionEvent actionEvent) throws IOException, SQLException, ClassNotFoundException {
myData = FXCollections.observableArrayList(DBCON.getEmployees());
System.out.println(myData.size());
Parent root = FXMLLoader.load(getClass().getResource("frmEmployees.fxml"));
Scene myScene = new Scene( root );
sample.MainController.setScene(myScene);
colFirstName.setCellValueFactory(new PropertyValueFactory<Employee, String>("firstName"));
colLastName.setCellValueFactory(new PropertyValueFactory<Employee, String>("lastName"));
colEmail.setCellValueFactory(new PropertyValueFactory<Employee, String>("email"));
employeesTable.setItems(null);
employeesTable.setItems(myData);
employeesTable.setVisible(true);
}
I get a null pointer exception when I go to set colFirstName to the property value factory which make me think I haven't initialized something somewhere but I am utterly clueless on how to go about adding that.
If I add in lines such as;
TableColumn colFirstName = new TableColumn("firstName");
for each of my columns and the tablename it works (ie it doesn't throw a load of error messages at me) that way but then I don't get any data loading into the tableview because I think that's me creating a new tableView not using the one generated from the FXML?
I have a feeling it will be very simple, but as I said I am a massive noob and any points would be much obliged.
Thanks
Mark
Update 1;
The method for load employee form is called from a button on myMain.fxml;
<GridPane alignment="CENTER" hgap="10" prefHeight="300" prefWidth="300" vgap="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8"
fx:controller="sample.TestController" stylesheets="/sample/myFirst.css">
<children>
<Button onAction="#login" text="Login" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="CENTER" />
<Button text="GoEmployees" onAction="#loadEmployeeForm" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER" />
<Label fx:id="login" GridPane.rowIndex="1" />
<Label text="UserName" GridPane.columnIndex="0" GridPane.rowIndex="1" />
<Label text="Password" GridPane.columnIndex="0" GridPane.rowIndex="2" />
<TextField fx:id="loginUserName" GridPane.rowIndex="1" GridPane.columnIndex="1" />
<PasswordField fx:id="loginPassword" GridPane.rowIndex="2" GridPane.columnIndex="1" blendMode="OVERLAY" />
<TextField fx:id="testOutput" GridPane.rowIndex="4" GridPane.columnIndex="0" GridPane.columnSpan="3" />
</children>
<columnConstraints>
<ColumnConstraints prefWidth="125.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints prefHeight="50.0" />
</rowConstraints>
<padding>
<Insets bottom="10.0" left="9.0" right="10.0" top="10.0" />
</padding>
</GridPane>
Is having my testController control two different FXMLs a problem/a no go?
When the FXMLLoader tries to load an fxml file, it will create new instance of the controller class defined with fx:controller in fxml file. Then it creates and maps the #FXML annotated fields with fx:id components in fxml file. Finally, it calls the controller's initialize() method. You can get the instantiated controller with fxmlloader.getController() after fxmlloader.load().
According to this basic work flow, the pitfall in your code is:
myMain.fxml's controller is TestController, but myMain.fxml does not contain TableColumns with fx:id colFirstName etc. So these fields are null, when the myMain.fxml has been loaded. As a result, there will be NPE in loadEmployeeForm() while trying to use these fields.
Move the TableView and TableColumns to frmEmployees.fxml's controller, and configure them (setCellValueFactory, initial data etc.) in this controller's initialize() method.
You never use your Employee(String, String, String) constructor. This constructor initializes the firstName, lastName, and email. Otherwise, your references will point to nothing.

Resources