Java FX Tableview not loading data from MYSQL DB [duplicate] - javafx

OK, new to java by several weeks, but have been programming for 30 years. The following code executes, but only the first column is showing anything. The data object is showing multiple rows of data, with fields of data that are filled in. I'm sure I'm missing something, and have looked through similar questions on here.
APVoucher_batchgridController.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
/**
* FXML Controller class
*
* #author kmitchell
*/
public class APVoucher_batchgridController implements Initializable {
public TableView tblMainList;
public TableColumn colDateEntered;
public TableColumn colCreatedBy;
public TableColumn colDescription;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
public void opentables(ActionEvent event) {
Object forName = null;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("DateEntered"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("cDesc"));
colCreatedBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("CreatedBy"));
try {
// load the driver into memory
forName = Class.forName("jstels.jdbc.dbf.DBFDriver2");
} catch (ClassNotFoundException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
try {
conn = DriverManager.getConnection("jdbc:jstels:dbf:e:\\keystone-data\\keyfund\\seymour\\keyfund.dbc");
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (conn != null) {
try {
stmt = conn.createStatement();
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (stmt != null) {
// execute a query
try {
ObservableList<Object> data = FXCollections.observableArrayList();
rs = stmt.executeQuery("SELECT denteredon, cdesc, ccreatedby FROM apvbatch WHERE ldeleted = false ORDER BY denteredon DESC");
while (rs.next()) {
String enteredon = rs.getString("denteredon");
String desc = rs.getString("cdesc");
String createdby = rs.getString("ccreatedby");
sresult row = new sresult(createdby, enteredon, desc);
data.add(row);
}
tblMainList.setItems(data);
tblMainList.setVisible(true);
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class sresult {
private String DateEntered;
private String EnteredBy;
private String cDesc;
public sresult(String T, String d, String c) {
this.EnteredBy = T;
this.DateEntered = d;
this.cDesc = c;
}
public String getEnteredBy() {
return EnteredBy;
}
public void setEnteredBy(String T) {
EnteredBy = T;
}
public String getDateEntered() {
return DateEntered;
}
public void setDateEntered(String d) {
DateEntered = d;
}
public String getcDesc() {
return cDesc;
}
public void setcDesc(String c) {
cDesc = c;
}
}
}
and APVoucher_batchgrid.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" fx:id="batchlistform" prefHeight="400.0" prefWidth="600.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="keystone.APVoucher_batchgridController">
<children>
<BorderPane layoutX="0.0" layoutY="0.0" prefHeight="400.0" prefWidth="600.0">
<center>
<AnchorPane prefHeight="-1.0" prefWidth="-1.0">
<children>
<Pane layoutX="0.0" layoutY="0.0" prefHeight="53.0" prefWidth="580.0">
<children>
<Label layoutX="7.0" layoutY="9.0" prefWidth="202.0" text="AP Vouchers Batch List">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Button fx:id="btnClose" cancelButton="true" layoutX="513.0" layoutY="27.0" mnemonicParsing="false" text="Close" />
<Button id="btnClose" fx:id="apvRefresh" cancelButton="true" layoutX="185.0" layoutY="27.0" mnemonicParsing="false" onAction="#opentables" text="Refresh" />
</children>
</Pane>
<TableView fx:id="tblMainList" layoutX="0.0" layoutY="53.0" prefHeight="323.0" prefWidth="580.0">
<columns>
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="91.0" text="Date Entered" fx:id="colDateEntered" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="100.0" text="Created By" fx:id="colCreatedBy" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="261.0" text="Description" fx:id="colDescription" />
</columns>
</TableView>
</children>
</AnchorPane>
</center>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</BorderPane>
</children>
<stylesheets>
<URL value="#apvoucher_batchgrid.css" />
</stylesheets>
</AnchorPane>
THANK YOU for the answer. Way to many years in case insensitive languages. This has been a quick and dirty exercise for me to learn java and the latest & greatest stuff or as I like to say New Exciting Technology (NExT!)
For anyone looking at the answer and still not completely clued in, here are the changes that made the code work properly.
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("Denteredon"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("CDesc"));
colEnteredBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("Ccreatedby"));
public class sresult {
private String Denteredon;
private String Ccreatedby;
private String CDesc;
public sresult(String T, String d, String c) {
this.Ccreatedby = T;
this.Denteredon = d;
this.CDesc = c;
}
public String getCcreatedby() {
return Ccreatedby;
}
public void setCreatedby(String T) {
Ccreatedby = T;
}
public String getDenteredon() {
return Denteredon;
}
public void setDenteredon(String d) {
Denteredon = d;
}
public String getCDesc() {
return CDesc;
}
public void setCDesc(String c) {
CDesc = c;
}
}
}

This question is really a duplicate of: Javafx PropertyValueFactory not populating Tableview, but I'll specifically address your specific case, so it's clear.
Suggested solution (use a Lambda, not a PropertyValueFactory)
Instead of:
aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Write:
aColumn.setCellValueFactory(cellData -> cellData.getValue().dateProperty());
For more information, see this answer:
Java: setCellValuefactory; Lambda vs. PropertyValueFactory; advantages/disadvantages
How do you use a JavaFX TableView with java records?
demonstrates replacing PropertyValueFactory with lambda expressions.
Solution using PropertyValueFactory
The lambda solution outlined above is preferred, but if you wish to use PropertyValueFactory, this alternate solution provides information on that.
Background
PropertyValueFactory uses reflection to determine the methods to get and set data values as well as to retrieve bindable properties from your model class. The pattern followed is:
PropertyValueType getName()
void setName(PropertyValueType value)
PropertyType nameProperty()
Where "name" is the string specified in the PropertyValueFactory constructor. The first letter of the property name in the getter and setter is capitalized (by java bean naming convention).
Why your application doesn't work
You have these three expressions:
new PropertyValueFactory<sresult, String>("DateEntered")
new PropertyValueFactory<sresult, String>("cDesc")
new PropertyValueFactory<sresult, String>("CreatedBy")
For your sample properties, the PropertyValueFactory will look for these methods:
"DateEntered" => getDateEntered()
"cDesc" => getCDesc()
"CreatedBy" => getCreatedBy()
And you have these three getters on your sresult class:
getDateEntered()
getcDesc()
getEnteredBy()
Only getDateEntered() is going to be picked up by the PropertyValueFactory because that is the only matching method defined in the sresult class.
Advice
You will have to adopt Java standards if you want the reflection in PropertyValueFactory to work (the alternative is to not use the PropertyValueFactory and instead write your own cell factories from scratch).
Adopting Java camel case naming conventions also makes it easier for Java developers to read your code.

Some times columns doesn't show data because of column names. eg,
new PropertyValueFactory<sresult, String>("cDesc")
and getter is getcDesc cDesc column may not display data. If you change code to
new PropertyValueFactory<sresult, String>("CDesc")
and getter is getCDesc CDesc column may display data.

For anyone else who still wasn't getting it after going through the above, my problem was that I wasn't specifying my setters with the "public final" designation.

Related

Adding data to a TableColumn in a TableView using ObservableList [duplicate]

OK, new to java by several weeks, but have been programming for 30 years. The following code executes, but only the first column is showing anything. The data object is showing multiple rows of data, with fields of data that are filled in. I'm sure I'm missing something, and have looked through similar questions on here.
APVoucher_batchgridController.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
/**
* FXML Controller class
*
* #author kmitchell
*/
public class APVoucher_batchgridController implements Initializable {
public TableView tblMainList;
public TableColumn colDateEntered;
public TableColumn colCreatedBy;
public TableColumn colDescription;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
public void opentables(ActionEvent event) {
Object forName = null;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("DateEntered"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("cDesc"));
colCreatedBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("CreatedBy"));
try {
// load the driver into memory
forName = Class.forName("jstels.jdbc.dbf.DBFDriver2");
} catch (ClassNotFoundException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
try {
conn = DriverManager.getConnection("jdbc:jstels:dbf:e:\\keystone-data\\keyfund\\seymour\\keyfund.dbc");
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (conn != null) {
try {
stmt = conn.createStatement();
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (stmt != null) {
// execute a query
try {
ObservableList<Object> data = FXCollections.observableArrayList();
rs = stmt.executeQuery("SELECT denteredon, cdesc, ccreatedby FROM apvbatch WHERE ldeleted = false ORDER BY denteredon DESC");
while (rs.next()) {
String enteredon = rs.getString("denteredon");
String desc = rs.getString("cdesc");
String createdby = rs.getString("ccreatedby");
sresult row = new sresult(createdby, enteredon, desc);
data.add(row);
}
tblMainList.setItems(data);
tblMainList.setVisible(true);
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class sresult {
private String DateEntered;
private String EnteredBy;
private String cDesc;
public sresult(String T, String d, String c) {
this.EnteredBy = T;
this.DateEntered = d;
this.cDesc = c;
}
public String getEnteredBy() {
return EnteredBy;
}
public void setEnteredBy(String T) {
EnteredBy = T;
}
public String getDateEntered() {
return DateEntered;
}
public void setDateEntered(String d) {
DateEntered = d;
}
public String getcDesc() {
return cDesc;
}
public void setcDesc(String c) {
cDesc = c;
}
}
}
and APVoucher_batchgrid.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" fx:id="batchlistform" prefHeight="400.0" prefWidth="600.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="keystone.APVoucher_batchgridController">
<children>
<BorderPane layoutX="0.0" layoutY="0.0" prefHeight="400.0" prefWidth="600.0">
<center>
<AnchorPane prefHeight="-1.0" prefWidth="-1.0">
<children>
<Pane layoutX="0.0" layoutY="0.0" prefHeight="53.0" prefWidth="580.0">
<children>
<Label layoutX="7.0" layoutY="9.0" prefWidth="202.0" text="AP Vouchers Batch List">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Button fx:id="btnClose" cancelButton="true" layoutX="513.0" layoutY="27.0" mnemonicParsing="false" text="Close" />
<Button id="btnClose" fx:id="apvRefresh" cancelButton="true" layoutX="185.0" layoutY="27.0" mnemonicParsing="false" onAction="#opentables" text="Refresh" />
</children>
</Pane>
<TableView fx:id="tblMainList" layoutX="0.0" layoutY="53.0" prefHeight="323.0" prefWidth="580.0">
<columns>
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="91.0" text="Date Entered" fx:id="colDateEntered" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="100.0" text="Created By" fx:id="colCreatedBy" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="261.0" text="Description" fx:id="colDescription" />
</columns>
</TableView>
</children>
</AnchorPane>
</center>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</BorderPane>
</children>
<stylesheets>
<URL value="#apvoucher_batchgrid.css" />
</stylesheets>
</AnchorPane>
THANK YOU for the answer. Way to many years in case insensitive languages. This has been a quick and dirty exercise for me to learn java and the latest & greatest stuff or as I like to say New Exciting Technology (NExT!)
For anyone looking at the answer and still not completely clued in, here are the changes that made the code work properly.
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("Denteredon"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("CDesc"));
colEnteredBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("Ccreatedby"));
public class sresult {
private String Denteredon;
private String Ccreatedby;
private String CDesc;
public sresult(String T, String d, String c) {
this.Ccreatedby = T;
this.Denteredon = d;
this.CDesc = c;
}
public String getCcreatedby() {
return Ccreatedby;
}
public void setCreatedby(String T) {
Ccreatedby = T;
}
public String getDenteredon() {
return Denteredon;
}
public void setDenteredon(String d) {
Denteredon = d;
}
public String getCDesc() {
return CDesc;
}
public void setCDesc(String c) {
CDesc = c;
}
}
}
This question is really a duplicate of: Javafx PropertyValueFactory not populating Tableview, but I'll specifically address your specific case, so it's clear.
Suggested solution (use a Lambda, not a PropertyValueFactory)
Instead of:
aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Write:
aColumn.setCellValueFactory(cellData -> cellData.getValue().dateProperty());
For more information, see this answer:
Java: setCellValuefactory; Lambda vs. PropertyValueFactory; advantages/disadvantages
How do you use a JavaFX TableView with java records?
demonstrates replacing PropertyValueFactory with lambda expressions.
Solution using PropertyValueFactory
The lambda solution outlined above is preferred, but if you wish to use PropertyValueFactory, this alternate solution provides information on that.
Background
PropertyValueFactory uses reflection to determine the methods to get and set data values as well as to retrieve bindable properties from your model class. The pattern followed is:
PropertyValueType getName()
void setName(PropertyValueType value)
PropertyType nameProperty()
Where "name" is the string specified in the PropertyValueFactory constructor. The first letter of the property name in the getter and setter is capitalized (by java bean naming convention).
Why your application doesn't work
You have these three expressions:
new PropertyValueFactory<sresult, String>("DateEntered")
new PropertyValueFactory<sresult, String>("cDesc")
new PropertyValueFactory<sresult, String>("CreatedBy")
For your sample properties, the PropertyValueFactory will look for these methods:
"DateEntered" => getDateEntered()
"cDesc" => getCDesc()
"CreatedBy" => getCreatedBy()
And you have these three getters on your sresult class:
getDateEntered()
getcDesc()
getEnteredBy()
Only getDateEntered() is going to be picked up by the PropertyValueFactory because that is the only matching method defined in the sresult class.
Advice
You will have to adopt Java standards if you want the reflection in PropertyValueFactory to work (the alternative is to not use the PropertyValueFactory and instead write your own cell factories from scratch).
Adopting Java camel case naming conventions also makes it easier for Java developers to read your code.
Some times columns doesn't show data because of column names. eg,
new PropertyValueFactory<sresult, String>("cDesc")
and getter is getcDesc cDesc column may not display data. If you change code to
new PropertyValueFactory<sresult, String>("CDesc")
and getter is getCDesc CDesc column may display data.
For anyone else who still wasn't getting it after going through the above, my problem was that I wasn't specifying my setters with the "public final" designation.

Troubleshooting Populating a tableview with Sqlite JavaFx [duplicate]

OK, new to java by several weeks, but have been programming for 30 years. The following code executes, but only the first column is showing anything. The data object is showing multiple rows of data, with fields of data that are filled in. I'm sure I'm missing something, and have looked through similar questions on here.
APVoucher_batchgridController.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
/**
* FXML Controller class
*
* #author kmitchell
*/
public class APVoucher_batchgridController implements Initializable {
public TableView tblMainList;
public TableColumn colDateEntered;
public TableColumn colCreatedBy;
public TableColumn colDescription;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
public void opentables(ActionEvent event) {
Object forName = null;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("DateEntered"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("cDesc"));
colCreatedBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("CreatedBy"));
try {
// load the driver into memory
forName = Class.forName("jstels.jdbc.dbf.DBFDriver2");
} catch (ClassNotFoundException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
try {
conn = DriverManager.getConnection("jdbc:jstels:dbf:e:\\keystone-data\\keyfund\\seymour\\keyfund.dbc");
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (conn != null) {
try {
stmt = conn.createStatement();
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (stmt != null) {
// execute a query
try {
ObservableList<Object> data = FXCollections.observableArrayList();
rs = stmt.executeQuery("SELECT denteredon, cdesc, ccreatedby FROM apvbatch WHERE ldeleted = false ORDER BY denteredon DESC");
while (rs.next()) {
String enteredon = rs.getString("denteredon");
String desc = rs.getString("cdesc");
String createdby = rs.getString("ccreatedby");
sresult row = new sresult(createdby, enteredon, desc);
data.add(row);
}
tblMainList.setItems(data);
tblMainList.setVisible(true);
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class sresult {
private String DateEntered;
private String EnteredBy;
private String cDesc;
public sresult(String T, String d, String c) {
this.EnteredBy = T;
this.DateEntered = d;
this.cDesc = c;
}
public String getEnteredBy() {
return EnteredBy;
}
public void setEnteredBy(String T) {
EnteredBy = T;
}
public String getDateEntered() {
return DateEntered;
}
public void setDateEntered(String d) {
DateEntered = d;
}
public String getcDesc() {
return cDesc;
}
public void setcDesc(String c) {
cDesc = c;
}
}
}
and APVoucher_batchgrid.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" fx:id="batchlistform" prefHeight="400.0" prefWidth="600.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="keystone.APVoucher_batchgridController">
<children>
<BorderPane layoutX="0.0" layoutY="0.0" prefHeight="400.0" prefWidth="600.0">
<center>
<AnchorPane prefHeight="-1.0" prefWidth="-1.0">
<children>
<Pane layoutX="0.0" layoutY="0.0" prefHeight="53.0" prefWidth="580.0">
<children>
<Label layoutX="7.0" layoutY="9.0" prefWidth="202.0" text="AP Vouchers Batch List">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Button fx:id="btnClose" cancelButton="true" layoutX="513.0" layoutY="27.0" mnemonicParsing="false" text="Close" />
<Button id="btnClose" fx:id="apvRefresh" cancelButton="true" layoutX="185.0" layoutY="27.0" mnemonicParsing="false" onAction="#opentables" text="Refresh" />
</children>
</Pane>
<TableView fx:id="tblMainList" layoutX="0.0" layoutY="53.0" prefHeight="323.0" prefWidth="580.0">
<columns>
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="91.0" text="Date Entered" fx:id="colDateEntered" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="100.0" text="Created By" fx:id="colCreatedBy" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="261.0" text="Description" fx:id="colDescription" />
</columns>
</TableView>
</children>
</AnchorPane>
</center>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</BorderPane>
</children>
<stylesheets>
<URL value="#apvoucher_batchgrid.css" />
</stylesheets>
</AnchorPane>
THANK YOU for the answer. Way to many years in case insensitive languages. This has been a quick and dirty exercise for me to learn java and the latest & greatest stuff or as I like to say New Exciting Technology (NExT!)
For anyone looking at the answer and still not completely clued in, here are the changes that made the code work properly.
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("Denteredon"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("CDesc"));
colEnteredBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("Ccreatedby"));
public class sresult {
private String Denteredon;
private String Ccreatedby;
private String CDesc;
public sresult(String T, String d, String c) {
this.Ccreatedby = T;
this.Denteredon = d;
this.CDesc = c;
}
public String getCcreatedby() {
return Ccreatedby;
}
public void setCreatedby(String T) {
Ccreatedby = T;
}
public String getDenteredon() {
return Denteredon;
}
public void setDenteredon(String d) {
Denteredon = d;
}
public String getCDesc() {
return CDesc;
}
public void setCDesc(String c) {
CDesc = c;
}
}
}
This question is really a duplicate of: Javafx PropertyValueFactory not populating Tableview, but I'll specifically address your specific case, so it's clear.
Suggested solution (use a Lambda, not a PropertyValueFactory)
Instead of:
aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Write:
aColumn.setCellValueFactory(cellData -> cellData.getValue().dateProperty());
For more information, see this answer:
Java: setCellValuefactory; Lambda vs. PropertyValueFactory; advantages/disadvantages
How do you use a JavaFX TableView with java records?
demonstrates replacing PropertyValueFactory with lambda expressions.
Solution using PropertyValueFactory
The lambda solution outlined above is preferred, but if you wish to use PropertyValueFactory, this alternate solution provides information on that.
Background
PropertyValueFactory uses reflection to determine the methods to get and set data values as well as to retrieve bindable properties from your model class. The pattern followed is:
PropertyValueType getName()
void setName(PropertyValueType value)
PropertyType nameProperty()
Where "name" is the string specified in the PropertyValueFactory constructor. The first letter of the property name in the getter and setter is capitalized (by java bean naming convention).
Why your application doesn't work
You have these three expressions:
new PropertyValueFactory<sresult, String>("DateEntered")
new PropertyValueFactory<sresult, String>("cDesc")
new PropertyValueFactory<sresult, String>("CreatedBy")
For your sample properties, the PropertyValueFactory will look for these methods:
"DateEntered" => getDateEntered()
"cDesc" => getCDesc()
"CreatedBy" => getCreatedBy()
And you have these three getters on your sresult class:
getDateEntered()
getcDesc()
getEnteredBy()
Only getDateEntered() is going to be picked up by the PropertyValueFactory because that is the only matching method defined in the sresult class.
Advice
You will have to adopt Java standards if you want the reflection in PropertyValueFactory to work (the alternative is to not use the PropertyValueFactory and instead write your own cell factories from scratch).
Adopting Java camel case naming conventions also makes it easier for Java developers to read your code.
Some times columns doesn't show data because of column names. eg,
new PropertyValueFactory<sresult, String>("cDesc")
and getter is getcDesc cDesc column may not display data. If you change code to
new PropertyValueFactory<sresult, String>("CDesc")
and getter is getCDesc CDesc column may display data.
For anyone else who still wasn't getting it after going through the above, my problem was that I wasn't specifying my setters with the "public final" designation.

trouble displaying data in tableview [duplicate]

OK, new to java by several weeks, but have been programming for 30 years. The following code executes, but only the first column is showing anything. The data object is showing multiple rows of data, with fields of data that are filled in. I'm sure I'm missing something, and have looked through similar questions on here.
APVoucher_batchgridController.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
/**
* FXML Controller class
*
* #author kmitchell
*/
public class APVoucher_batchgridController implements Initializable {
public TableView tblMainList;
public TableColumn colDateEntered;
public TableColumn colCreatedBy;
public TableColumn colDescription;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
public void opentables(ActionEvent event) {
Object forName = null;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("DateEntered"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("cDesc"));
colCreatedBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("CreatedBy"));
try {
// load the driver into memory
forName = Class.forName("jstels.jdbc.dbf.DBFDriver2");
} catch (ClassNotFoundException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
try {
conn = DriverManager.getConnection("jdbc:jstels:dbf:e:\\keystone-data\\keyfund\\seymour\\keyfund.dbc");
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (conn != null) {
try {
stmt = conn.createStatement();
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (stmt != null) {
// execute a query
try {
ObservableList<Object> data = FXCollections.observableArrayList();
rs = stmt.executeQuery("SELECT denteredon, cdesc, ccreatedby FROM apvbatch WHERE ldeleted = false ORDER BY denteredon DESC");
while (rs.next()) {
String enteredon = rs.getString("denteredon");
String desc = rs.getString("cdesc");
String createdby = rs.getString("ccreatedby");
sresult row = new sresult(createdby, enteredon, desc);
data.add(row);
}
tblMainList.setItems(data);
tblMainList.setVisible(true);
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class sresult {
private String DateEntered;
private String EnteredBy;
private String cDesc;
public sresult(String T, String d, String c) {
this.EnteredBy = T;
this.DateEntered = d;
this.cDesc = c;
}
public String getEnteredBy() {
return EnteredBy;
}
public void setEnteredBy(String T) {
EnteredBy = T;
}
public String getDateEntered() {
return DateEntered;
}
public void setDateEntered(String d) {
DateEntered = d;
}
public String getcDesc() {
return cDesc;
}
public void setcDesc(String c) {
cDesc = c;
}
}
}
and APVoucher_batchgrid.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" fx:id="batchlistform" prefHeight="400.0" prefWidth="600.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="keystone.APVoucher_batchgridController">
<children>
<BorderPane layoutX="0.0" layoutY="0.0" prefHeight="400.0" prefWidth="600.0">
<center>
<AnchorPane prefHeight="-1.0" prefWidth="-1.0">
<children>
<Pane layoutX="0.0" layoutY="0.0" prefHeight="53.0" prefWidth="580.0">
<children>
<Label layoutX="7.0" layoutY="9.0" prefWidth="202.0" text="AP Vouchers Batch List">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Button fx:id="btnClose" cancelButton="true" layoutX="513.0" layoutY="27.0" mnemonicParsing="false" text="Close" />
<Button id="btnClose" fx:id="apvRefresh" cancelButton="true" layoutX="185.0" layoutY="27.0" mnemonicParsing="false" onAction="#opentables" text="Refresh" />
</children>
</Pane>
<TableView fx:id="tblMainList" layoutX="0.0" layoutY="53.0" prefHeight="323.0" prefWidth="580.0">
<columns>
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="91.0" text="Date Entered" fx:id="colDateEntered" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="100.0" text="Created By" fx:id="colCreatedBy" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="261.0" text="Description" fx:id="colDescription" />
</columns>
</TableView>
</children>
</AnchorPane>
</center>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</BorderPane>
</children>
<stylesheets>
<URL value="#apvoucher_batchgrid.css" />
</stylesheets>
</AnchorPane>
THANK YOU for the answer. Way to many years in case insensitive languages. This has been a quick and dirty exercise for me to learn java and the latest & greatest stuff or as I like to say New Exciting Technology (NExT!)
For anyone looking at the answer and still not completely clued in, here are the changes that made the code work properly.
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("Denteredon"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("CDesc"));
colEnteredBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("Ccreatedby"));
public class sresult {
private String Denteredon;
private String Ccreatedby;
private String CDesc;
public sresult(String T, String d, String c) {
this.Ccreatedby = T;
this.Denteredon = d;
this.CDesc = c;
}
public String getCcreatedby() {
return Ccreatedby;
}
public void setCreatedby(String T) {
Ccreatedby = T;
}
public String getDenteredon() {
return Denteredon;
}
public void setDenteredon(String d) {
Denteredon = d;
}
public String getCDesc() {
return CDesc;
}
public void setCDesc(String c) {
CDesc = c;
}
}
}
This question is really a duplicate of: Javafx PropertyValueFactory not populating Tableview, but I'll specifically address your specific case, so it's clear.
Suggested solution (use a Lambda, not a PropertyValueFactory)
Instead of:
aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Write:
aColumn.setCellValueFactory(cellData -> cellData.getValue().dateProperty());
For more information, see this answer:
Java: setCellValuefactory; Lambda vs. PropertyValueFactory; advantages/disadvantages
How do you use a JavaFX TableView with java records?
demonstrates replacing PropertyValueFactory with lambda expressions.
Solution using PropertyValueFactory
The lambda solution outlined above is preferred, but if you wish to use PropertyValueFactory, this alternate solution provides information on that.
Background
PropertyValueFactory uses reflection to determine the methods to get and set data values as well as to retrieve bindable properties from your model class. The pattern followed is:
PropertyValueType getName()
void setName(PropertyValueType value)
PropertyType nameProperty()
Where "name" is the string specified in the PropertyValueFactory constructor. The first letter of the property name in the getter and setter is capitalized (by java bean naming convention).
Why your application doesn't work
You have these three expressions:
new PropertyValueFactory<sresult, String>("DateEntered")
new PropertyValueFactory<sresult, String>("cDesc")
new PropertyValueFactory<sresult, String>("CreatedBy")
For your sample properties, the PropertyValueFactory will look for these methods:
"DateEntered" => getDateEntered()
"cDesc" => getCDesc()
"CreatedBy" => getCreatedBy()
And you have these three getters on your sresult class:
getDateEntered()
getcDesc()
getEnteredBy()
Only getDateEntered() is going to be picked up by the PropertyValueFactory because that is the only matching method defined in the sresult class.
Advice
You will have to adopt Java standards if you want the reflection in PropertyValueFactory to work (the alternative is to not use the PropertyValueFactory and instead write your own cell factories from scratch).
Adopting Java camel case naming conventions also makes it easier for Java developers to read your code.
Some times columns doesn't show data because of column names. eg,
new PropertyValueFactory<sresult, String>("cDesc")
and getter is getcDesc cDesc column may not display data. If you change code to
new PropertyValueFactory<sresult, String>("CDesc")
and getter is getCDesc CDesc column may display data.
For anyone else who still wasn't getting it after going through the above, my problem was that I wasn't specifying my setters with the "public final" designation.

Managing data inside a controller [duplicate]

OK, new to java by several weeks, but have been programming for 30 years. The following code executes, but only the first column is showing anything. The data object is showing multiple rows of data, with fields of data that are filled in. I'm sure I'm missing something, and have looked through similar questions on here.
APVoucher_batchgridController.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
/**
* FXML Controller class
*
* #author kmitchell
*/
public class APVoucher_batchgridController implements Initializable {
public TableView tblMainList;
public TableColumn colDateEntered;
public TableColumn colCreatedBy;
public TableColumn colDescription;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
public void opentables(ActionEvent event) {
Object forName = null;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("DateEntered"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("cDesc"));
colCreatedBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("CreatedBy"));
try {
// load the driver into memory
forName = Class.forName("jstels.jdbc.dbf.DBFDriver2");
} catch (ClassNotFoundException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
try {
conn = DriverManager.getConnection("jdbc:jstels:dbf:e:\\keystone-data\\keyfund\\seymour\\keyfund.dbc");
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (conn != null) {
try {
stmt = conn.createStatement();
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
if (stmt != null) {
// execute a query
try {
ObservableList<Object> data = FXCollections.observableArrayList();
rs = stmt.executeQuery("SELECT denteredon, cdesc, ccreatedby FROM apvbatch WHERE ldeleted = false ORDER BY denteredon DESC");
while (rs.next()) {
String enteredon = rs.getString("denteredon");
String desc = rs.getString("cdesc");
String createdby = rs.getString("ccreatedby");
sresult row = new sresult(createdby, enteredon, desc);
data.add(row);
}
tblMainList.setItems(data);
tblMainList.setVisible(true);
} catch (SQLException ex) {
Logger.getLogger(APVoucher_batchgridController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class sresult {
private String DateEntered;
private String EnteredBy;
private String cDesc;
public sresult(String T, String d, String c) {
this.EnteredBy = T;
this.DateEntered = d;
this.cDesc = c;
}
public String getEnteredBy() {
return EnteredBy;
}
public void setEnteredBy(String T) {
EnteredBy = T;
}
public String getDateEntered() {
return DateEntered;
}
public void setDateEntered(String d) {
DateEntered = d;
}
public String getcDesc() {
return cDesc;
}
public void setcDesc(String c) {
cDesc = c;
}
}
}
and APVoucher_batchgrid.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" fx:id="batchlistform" prefHeight="400.0" prefWidth="600.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="keystone.APVoucher_batchgridController">
<children>
<BorderPane layoutX="0.0" layoutY="0.0" prefHeight="400.0" prefWidth="600.0">
<center>
<AnchorPane prefHeight="-1.0" prefWidth="-1.0">
<children>
<Pane layoutX="0.0" layoutY="0.0" prefHeight="53.0" prefWidth="580.0">
<children>
<Label layoutX="7.0" layoutY="9.0" prefWidth="202.0" text="AP Vouchers Batch List">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Button fx:id="btnClose" cancelButton="true" layoutX="513.0" layoutY="27.0" mnemonicParsing="false" text="Close" />
<Button id="btnClose" fx:id="apvRefresh" cancelButton="true" layoutX="185.0" layoutY="27.0" mnemonicParsing="false" onAction="#opentables" text="Refresh" />
</children>
</Pane>
<TableView fx:id="tblMainList" layoutX="0.0" layoutY="53.0" prefHeight="323.0" prefWidth="580.0">
<columns>
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="91.0" text="Date Entered" fx:id="colDateEntered" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="100.0" text="Created By" fx:id="colCreatedBy" />
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="261.0" text="Description" fx:id="colDescription" />
</columns>
</TableView>
</children>
</AnchorPane>
</center>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</BorderPane>
</children>
<stylesheets>
<URL value="#apvoucher_batchgrid.css" />
</stylesheets>
</AnchorPane>
THANK YOU for the answer. Way to many years in case insensitive languages. This has been a quick and dirty exercise for me to learn java and the latest & greatest stuff or as I like to say New Exciting Technology (NExT!)
For anyone looking at the answer and still not completely clued in, here are the changes that made the code work properly.
colDateEntered.setCellValueFactory(new PropertyValueFactory<sresult, String>("Denteredon"));
colDescription.setCellValueFactory(new PropertyValueFactory<sresult, String>("CDesc"));
colEnteredBy.setCellValueFactory(new PropertyValueFactory<sresult, String>("Ccreatedby"));
public class sresult {
private String Denteredon;
private String Ccreatedby;
private String CDesc;
public sresult(String T, String d, String c) {
this.Ccreatedby = T;
this.Denteredon = d;
this.CDesc = c;
}
public String getCcreatedby() {
return Ccreatedby;
}
public void setCreatedby(String T) {
Ccreatedby = T;
}
public String getDenteredon() {
return Denteredon;
}
public void setDenteredon(String d) {
Denteredon = d;
}
public String getCDesc() {
return CDesc;
}
public void setCDesc(String c) {
CDesc = c;
}
}
}
This question is really a duplicate of: Javafx PropertyValueFactory not populating Tableview, but I'll specifically address your specific case, so it's clear.
Suggested solution (use a Lambda, not a PropertyValueFactory)
Instead of:
aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Write:
aColumn.setCellValueFactory(cellData -> cellData.getValue().dateProperty());
For more information, see this answer:
Java: setCellValuefactory; Lambda vs. PropertyValueFactory; advantages/disadvantages
How do you use a JavaFX TableView with java records?
demonstrates replacing PropertyValueFactory with lambda expressions.
Solution using PropertyValueFactory
The lambda solution outlined above is preferred, but if you wish to use PropertyValueFactory, this alternate solution provides information on that.
Background
PropertyValueFactory uses reflection to determine the methods to get and set data values as well as to retrieve bindable properties from your model class. The pattern followed is:
PropertyValueType getName()
void setName(PropertyValueType value)
PropertyType nameProperty()
Where "name" is the string specified in the PropertyValueFactory constructor. The first letter of the property name in the getter and setter is capitalized (by java bean naming convention).
Why your application doesn't work
You have these three expressions:
new PropertyValueFactory<sresult, String>("DateEntered")
new PropertyValueFactory<sresult, String>("cDesc")
new PropertyValueFactory<sresult, String>("CreatedBy")
For your sample properties, the PropertyValueFactory will look for these methods:
"DateEntered" => getDateEntered()
"cDesc" => getCDesc()
"CreatedBy" => getCreatedBy()
And you have these three getters on your sresult class:
getDateEntered()
getcDesc()
getEnteredBy()
Only getDateEntered() is going to be picked up by the PropertyValueFactory because that is the only matching method defined in the sresult class.
Advice
You will have to adopt Java standards if you want the reflection in PropertyValueFactory to work (the alternative is to not use the PropertyValueFactory and instead write your own cell factories from scratch).
Adopting Java camel case naming conventions also makes it easier for Java developers to read your code.
Some times columns doesn't show data because of column names. eg,
new PropertyValueFactory<sresult, String>("cDesc")
and getter is getcDesc cDesc column may not display data. If you change code to
new PropertyValueFactory<sresult, String>("CDesc")
and getter is getCDesc CDesc column may display data.
For anyone else who still wasn't getting it after going through the above, my problem was that I wasn't specifying my setters with the "public final" designation.

Is it possible combine fx:include and afterburner

I currently using afterburner.fx to tailor together components of JavaFX based application.
Right now I trying move components in separate fxml files for more comfortable maintenance.
To load such components I using fx:include directive which allow load nested components automatically.
Problem is that with automatic load I loosing possibility get presenter from nested view.
Is there a way to combine automatic load and in same time, be able work with nested components from parent root?
These two seem to work fine together.
Afterburner works by setting a controller factory on the FXML loader, which takes care of instantiating the presenter class and injecting values into it.
The <fx:include> element will propagate the controller factory when loading the included FXML, so you can also inject values into the controller defined in the included FXML. Because afterburner effectively uses a singleton scope for injection, the same instance of injected fields will be used. This means you can readily share your data model between the different presenter classes.
If you want access to the presenter associated with the included FXML, just use the standard technique for "nested controllers".
So, for example:
main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.geometry.Insets?>
<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="application.MainPresenter">
<center>
<TableView fx:id="table">
<columns>
<TableColumn text="First Name" prefWidth="150">
<cellValueFactory>
<PropertyValueFactory property="firstName" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Last Name" prefWidth="150">
<cellValueFactory>
<PropertyValueFactory property="lastName" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Email" prefWidth="200">
<cellValueFactory>
<PropertyValueFactory property="email" />
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
</center>
<bottom>
<fx:include source="Editor.fxml" fx:id="editor">
<padding>
<Insets top="5" bottom="5" left="5" right="5"/>
</padding>
</fx:include>
</bottom>
</BorderPane>
editor.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<GridPane xmlns:fx="http://javafx.com/fxml" hgap="5" vgap="10" fx:controller="application.EditorPresenter">
<Label GridPane.rowIndex="0" GridPane.columnIndex="0" text="First Name:"/>
<TextField fx:id="firstNameTextField" GridPane.rowIndex="0" GridPane.columnIndex="1"/>
<Label GridPane.rowIndex="1" GridPane.columnIndex="0" text="Last Name"/>
<TextField fx:id="lastNameTextField" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
<Label GridPane.rowIndex="2" GridPane.columnIndex="0" text="Email"/>
<TextField fx:id="emailTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
<HBox GridPane.rowIndex="3" GridPane.columnIndex="0" GridPane.columnSpan="2">
<Button fx:id="addEditButton" onAction="#addEdit" />
</HBox>
</GridPane>
MainPresenter.java:
package application;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
public class MainPresenter {
#FXML
private TableView<Person> table ;
// This is the controller (presenter) for the included fxml
// It is injected by the FXMLLoader; the rule is that "Controller" needs to be
// appended to the fx:id attribute of the <fx:include> tag.
// This is not used in this example but is here to demonstrate how to access it
// if needed.
#FXML
private EditorPresenter editorController ;
#Inject
private DataModel dataModel ;
public void initialize() {
table.setItems(dataModel.getPeople());
table.getSelectionModel().selectedItemProperty().addListener(
(obs, oldPerson, newPerson) -> dataModel.setCurrentPerson(newPerson));
dataModel.currentPersonProperty().addListener((obs, oldPerson, newPerson) -> {
if (newPerson == null) {
table.getSelectionModel().clearSelection();
} else {
table.getSelectionModel().select(newPerson);
}
});
dataModel.getPeople().addAll(
new Person("Jacob", "Smith", "jacob.smith#example.com"),
new Person("Isabella", "Johnson", "isabella.johnson#example.com"),
new Person("Ethan", "Williams", "ethan.williams#example.com"),
new Person("Emma", "Jones", "emma.jones#example.com"),
new Person("Michael", "Brown", "michael.brown#example.com")
);
}
}
EditorPresenter.java:
package application;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javax.inject.Inject;
public class EditorPresenter {
#FXML
private TextField firstNameTextField ;
#FXML
private TextField lastNameTextField ;
#FXML
private TextField emailTextField ;
#FXML
private Button addEditButton ;
#Inject
private DataModel dataModel ;
public void initialize() {
addEditButton.textProperty().bind(
Bindings.when(Bindings.isNull(dataModel.currentPersonProperty()))
.then("Add")
.otherwise("Update")
);
dataModel.currentPersonProperty().addListener((obs, oldPerson, newPerson) -> {
if (newPerson == null) {
firstNameTextField.setText("");
lastNameTextField.setText("");
emailTextField.setText("");
} else {
firstNameTextField.setText(newPerson.getFirstName());
lastNameTextField.setText(newPerson.getLastName());
emailTextField.setText(newPerson.getEmail());
}
});
}
#FXML
private void addEdit() {
Person person = dataModel.getCurrentPerson();
String firstName = firstNameTextField.getText();
String lastName = lastNameTextField.getText();
String email = emailTextField.getText();
if (person == null) {
dataModel.getPeople().add(new Person(firstName, lastName, email));
} else {
person.setFirstName(firstName);
person.setLastName(lastName);
person.setEmail(email);
}
}
}
MainView.java:
package application;
import com.airhacks.afterburner.views.FXMLView;
public class MainView extends FXMLView {
}
Main.java (application class):
package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import com.airhacks.afterburner.injection.Injector;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
MainView mainView = new MainView();
Scene scene = new Scene(mainView.getView(), 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
#Override
public void stop() throws Exception {
Injector.forgetAll();
}
public static void main(String[] args) {
launch(args);
}
}
DataModel.java:
package application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class DataModel {
private final ObservableList<Person> people = FXCollections.observableArrayList();
private final ObjectProperty<Person> currentPerson = new SimpleObjectProperty<>(this, "currentPerson");
public ObservableList<Person> getPeople() {
return people ;
}
public final Person getCurrentPerson() {
return currentPerson.get();
}
public final void setCurrentPerson(Person person) {
this.currentPerson.set(person);
}
public ObjectProperty<Person> currentPersonProperty() {
return currentPerson ;
}
}
And the usual Person.java example:
package application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Person {
private final StringProperty firstName = new SimpleStringProperty(this, "firstName");
public final String getFirstName() {
return firstName.get();
}
public final void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public StringProperty firstNameProperty() {
return firstName ;
}
private final StringProperty lastName = new SimpleStringProperty(this, "lastName");
public final String getLastName() {
return lastName.get();
}
public final void setLastName(String lastName) {
this.lastName.set(lastName);
}
public StringProperty lastNameProperty() {
return lastName ;
}
private final StringProperty email = new SimpleStringProperty(this, "email");
public final String getEmail() {
return email.get();
}
public final void setEmail(String email) {
this.email.set(email);
}
public StringProperty emailProperty() {
return email ;
}
public Person(String firstName, String lastName, String email) {
setFirstName(firstName);
setLastName(lastName);
setEmail(email);
}
}

Resources