I'm doing this program in JavaFX that will take data from a database created on Microsoft access and place it on a table view. Also, I created button inside the table view (Add,Delete) when clicking on add button it will open a new FXML page. In this page there are 5 TextFiled and two button (Add and Cancel) when clicking on add button it suppose to take all the data in the TextFiled and add it to my table view. But i actually could not do that. I hope that someone here have an idea of how i can accomplish this.
FXMLDocumentController.java
package db;
import java.net.URL;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
*
* @author pc
*/
public class FXMLDocumentController implements Initializable {
@FXML
public Statement st;
public TableView<ObservableList> table;
public ObservableList<ObservableList> data;
private Button btnNew = new Button("New Record");
public void buildData(){
data = FXCollections.observableArrayList();
try{
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection con = DriverManager.getConnection("jdbc:ucanaccess://D:\\GUI\\Library.accdb","","");
System.out.println("connected...");
st=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
//SQL FOR SELECTING ALL OF BOOK
String SQL = "SELECT * from BookDB";
//ResultSet
ResultSet rs = con.createStatement().executeQuery(SQL);
/**********************************
* TABLE COLUMN ADDED DYNAMICALLY *
**********************************/
for(int i=0 ; i<rs.getMetaData().getColumnCount(); i++){
//We are using non property style for making dynamic table
final int j = i;
TableColumn col = new TableColumn(rs.getMetaData().getColumnName(i+1));
col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList,String>,ObservableValue<String>>(){
public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) {
return new SimpleStringProperty(param.getValue().get(j).toString());
}
});
table.getColumns().addAll(col);
System.out.println("Column ["+i+"] ");
}
TableColumn col_action = new TableColumn<>("Action");
col_action.setSortable(false);
col_action.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<ObservableList, Boolean>,
ObservableValue<Boolean>>() {
@Override
public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<ObservableList, Boolean> p) {
return new SimpleBooleanProperty(p.getValue() != null);
}
});
col_action.setCellFactory(
new Callback<TableColumn<ObservableList, Boolean>, TableCell<ObservableList, Boolean>>() {
@Override
public TableCell<ObservableList, Boolean> call(TableColumn<ObservableList, Boolean> p) {
return new ButtonCell(table);
}
});
table.getColumns().add(col_action);
TableColumn col_Delete = new TableColumn<>("Delete");
col_Delete.setSortable(false);
col_Delete.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<ObservableList, Boolean>,
ObservableValue<Boolean>>() {
@Override
public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<ObservableList, Boolean> p) {
return new SimpleBooleanProperty(p.getValue() != null);
}
});
col_Delete.setCellFactory(
new Callback<TableColumn<ObservableList, Boolean>, TableCell<ObservableList, Boolean>>() {
@Override
public TableCell<ObservableList, Boolean> call(TableColumn<ObservableList, Boolean> p) {
return new ButtonDelete(table);
}
});
table.getColumns().add(col_Delete);
/********************************
* Data added to ObservableList *
********************************/
while(rs.next()){
//Iterate Row
ObservableList<String> row = FXCollections.observableArrayList();
for(int i=1 ; i<=rs.getMetaData().getColumnCount(); i++){
//Iterate Column
row.add(rs.getString(i));
}
System.out.println("Row [1] added "+row );
data.add(row);
}
//FINALLY ADDED TO TableView
table.setItems(data);
}
catch(Exception e){
e.printStackTrace();
System.out.println("Error on Building Data");
}
}
@Override
public void initialize(URL url, ResourceBundle rb) {
buildData();
table.refresh();
}
//Define the button cell
private class ButtonCell extends TableCell<ObservableList, Boolean> {
final Button cellButton = new Button("Add");
ButtonCell(final TableView tblView){
cellButton.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent t) {
try {
Second s=new Second();
s.start(new Stage());
} catch (Exception ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
//Display button if the row is not empty
@Override
protected void updateItem(Boolean t, boolean empty) {
super.updateItem(t, empty);
if(!empty){
setGraphic(cellButton);
}
}
}
//Define the button cell
private class ButtonDelete extends TableCell<ObservableList, Boolean> {
final Button delButton = new Button("Delete");
ButtonDelete(final TableView tblView){
delButton.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent t) {
Stage myDialog = new Stage();
myDialog.initModality(Modality.WINDOW_MODAL);
myDialog.show();
}
});
}
//Display button if the row is not empty
@Override
protected void updateItem(Boolean t, boolean empty) {
super.updateItem(t, empty);
if(!empty){
setGraphic(delButton);
}
}
}
}
FXMLController.java
package db;
import java.net.URL;
import java.sql.Statement;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
/**
* FXML Controller class
*
* @author pc
*/
public class FXMLController implements Initializable {
@FXML
public TextField t1,t2,t3,t4,t5;
public Statement st;
@FXML
public void btnADD(ActionEvent e)
{
}
@FXML
public void btnCANCEL(ActionEvent e)
{
System.exit(0);
}
@Override
public void initialize(URL url, ResourceBundle rb)
{
}
}
Database Structure
my friend, base on your code, i have made some reconstruction of your code to make it working, but the code's structure is not good, if it is mine project, i won't use this structure, LOL, just for reference. As below.
first, we need to create a TableView's generic type class, here we create Book.java for it.
package db;
public class Book{
private String id;
private String name;
private String author;
private String publisher;
private String price;
public String getId(){
return this.id;
}
public void setId(String id){
this.id = id;
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public String getAuthor(){
return this.author;
}
public void setAuthor(String author){
this.author = author;
}
public String getPublisher(){
return this.publisher;
}
public void setPublisher(String publisher){
this.publisher = publisher;
}
public String getPrice(){
return this.price;
}
public void setPrice(String price){
this.price = price;
}
@Override
public int hashCode(){
final int prime = 31;
int result = 1;
result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
return result;
}
@Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if(this.id == null){
if(other.id != null)
return false;
}else if(!this.id.equals(other.id))
return false;
return true;
}
public void setValue(String columnName, String colData){
if(columnName.contentEquals("BookName")){
setName(colData);
}else if(columnName.contentEquals("Author")){
setAuthor(colData);
}else if(columnName.contentEquals("Publisher")){
setPublisher(colData);
}else if(columnName.contentEquals("Price")){
setPrice(colData);
}else{
//BookId
setId(colData);
}
}
public String getValue(String columnName){
String value = "";
if(columnName.contentEquals("BookName")){
value = getName();
}else if(columnName.contentEquals("Author")){
value = getAuthor();
}else if(columnName.contentEquals("Publisher")){
value = getPublisher();
}else if(columnName.contentEquals("Price")){
value = getPrice();
}else{
//BookId
value = getId();
}
return value;
}
}
then modified your FXMLDocumentController.java as below:
package db;
import java.io.IOException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
*
* @author pc
*/
public class FXMLDocumentController implements Initializable{
public Statement st;
@FXML
public TableView<Book> table;
//public ObservableList<ObservableList> data;
private ObservableList<Book> bookData;
//private Button btnNew = new Button("New Record");
public void buildData(){
//data = FXCollections.observableArrayList();
bookData = FXCollections.observableArrayList();
try{
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection con = DriverManager.getConnection("jdbc:ucanaccess://D:\\GUI\\Library.accdb", "", "");
System.out.println("connected...");
st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
// SQL FOR SELECTING ALL OF BOOK
String SQL = "SELECT * from BookDB";
// ResultSet
ResultSet rs = con.createStatement().executeQuery(SQL);
/**********************************
* TABLE COLUMN ADDED DYNAMICALLY *
**********************************/
for(int i = 0; i < rs.getMetaData().getColumnCount(); i++){
// We are using non property style for making dynamic table
String columnName = rs.getMetaData().getColumnName(i + 1);
TableColumn<Book, String> col = new TableColumn<>(columnName);
col.setCellValueFactory(new Callback<CellDataFeatures<Book, String>, ObservableValue<String>>(){
public ObservableValue<String> call(CellDataFeatures<Book, String> param){
Book book = param.getValue();
String cellData = book.getValue(columnName);
return new SimpleStringProperty(cellData);
}
});
table.getColumns().add(col);
System.out.println("Column [" + i + "] ");
}
TableColumn<Book, Boolean> col_action = new TableColumn<>("Action");
col_action.setSortable(false);
col_action.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Book, Boolean>, ObservableValue<Boolean>>(){
@Override
public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Book, Boolean> p){
return new SimpleBooleanProperty(p.getValue() != null);
}
});
col_action.setCellFactory(new Callback<TableColumn<Book, Boolean>, TableCell<Book, Boolean>>(){
@Override
public TableCell<Book, Boolean> call(TableColumn<Book, Boolean> p){
return new ButtonCell(table);
}
});
table.getColumns().add(col_action);
TableColumn<Book, Boolean> col_Delete = new TableColumn<>("Delete");
col_Delete.setSortable(false);
col_Delete.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Book, Boolean>, ObservableValue<Boolean>>(){
@Override
public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Book, Boolean> p){
return new SimpleBooleanProperty(p.getValue() != null);
}
});
col_Delete.setCellFactory(new Callback<TableColumn<Book, Boolean>, TableCell<Book, Boolean>>(){
@Override
public TableCell<Book, Boolean> call(TableColumn<Book, Boolean> p){
return new ButtonDelete(table);
}
});
table.getColumns().add(col_Delete);
/********************************
* Data added to ObservableList *
********************************/
while(rs.next()){
Book book = new Book();
// Iterate Row
for(int i = 1; i <= rs.getMetaData().getColumnCount(); i++){
// Iterate Column
String columnName = rs.getMetaData().getColumnName(i);
String columnData = rs.getString(i);
book.setValue(columnName, columnData);
}
System.out.println("Row [1] added " + book.getName());
bookData.add(book);
}
// FINALLY ADDED TO TableView
table.setItems(bookData);
}catch(Exception e){
e.printStackTrace();
System.out.println("Error on Building Data");
}
}
@Override
public void initialize(URL url, ResourceBundle rb){
buildData();
table.refresh();
}
// Define the button cell
private class ButtonCell extends TableCell<Book, Boolean>{
final Button cellButton = new Button("Add");
ButtonCell(final TableView<Book> tblView) {
cellButton.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent t){
try{
//Second s = new Second();
//s.start(new Stage());
openFXMLController();
}catch(Exception ex){
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
// Display button if the row is not empty
@Override
protected void updateItem(Boolean t, boolean empty){
super.updateItem(t, empty);
if(!empty){
setGraphic(cellButton);
}else{
setGraphic(null);
setText("");
}
}
}
private Stage fxmlControllerStage;
private void openFXMLController(){
if(fxmlControllerStage == null){
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXML.fxml"));
try{
Parent root = loader.load();
fxmlControllerStage = new Stage();
fxmlControllerStage.setScene(new Scene(root));
if(loader.getController() instanceof FXMLController){
FXMLController fxmlController = loader.getController();
fxmlController.setStage(fxmlControllerStage);
fxmlController.setTable(table);
}
}catch(IOException e){
e.printStackTrace();
}
}
fxmlControllerStage.show();
}
// Define the button cell
private class ButtonDelete extends TableCell<Book, Boolean>{
final Button delButton = new Button("Delete");
ButtonDelete(final TableView<Book> tblView) {
delButton.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent t){
bookData.remove(getIndex());
}
});
}
// Display button if the row is not empty
@Override
protected void updateItem(Boolean t, boolean empty){
super.updateItem(t, empty);
if(!empty){
setGraphic(delButton);
}else{
setGraphic(null);
setText("");
}
}
}
}
and the last one is your FXMLController.java. we modified it as below:
package db;
import java.net.URL;
import java.sql.Statement;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
/**
* FXML Controller class
*
* @author pc
*/
public class FXMLController implements Initializable{
@FXML
public TextField t1;
@FXML
public TextField t2;
@FXML
public TextField t3;
@FXML
public TextField t4;
@FXML
public TextField t5;
public Statement st;
@FXML
public void btnADD(ActionEvent e){
Book book = new Book();
try{
Integer.valueOf(t1.getText());
}catch(NumberFormatException exception){
Alert alert = new Alert(AlertType.ERROR);
alert.setContentText("BookID must be an integer");
alert.showAndWait();
return;
}
try{
Double.valueOf(t5.getText());
}catch(NumberFormatException exception){
Alert alert = new Alert(AlertType.ERROR);
alert.setContentText("Price must be an integer");
alert.showAndWait();
return;
}
book.setId(t1.getText());
book.setName(t2.getText());
book.setAuthor(t3.getText());
book.setPublisher(t4.getText());
book.setPrice(t5.getText());
if(table != null){
table.getItems().add(book);
if(stage != null){
t1.clear();
t2.clear();
t3.clear();
t4.clear();
t5.clear();
stage.close();
}
}
}
@FXML
public void btnCANCEL(ActionEvent e){
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setContentText("Close Window, Are you sure?");
alert.showAndWait();
ButtonType result = alert.getResult();
if(result == ButtonType.OK){
if(stage != null){
stage.close();
}
}
//System.exit(0);
}
@Override
public void initialize(URL url, ResourceBundle rb){
}
private Stage stage;
public void setStage(Stage stage){
this.stage = stage;
}
private TableView<Book> table;
public void setTable(TableView<Book> table){
this.table = table;
}
}
we delete the Second.java, because it does nothing.