I am trying to create a JavaFX program to manage a production line. I am working with a database so that the user can populate a database with TextField and ChoiceBox. I am having trouble filling a ChoiceBox from an Enum class that I have created.
It is expected that my ChoiceBox is populated with items from my Enum class, however, the ChoiceBox is staying blank. The code is compiling.
Before you refer me to this link, I have tried using the advice in that discussion, but I am unable to wrap my head around it. That discussion does not help because I am not sure where they are trying to populate their ComboBox. Also, cbxStatus.getItems().setAll(Status.values()); is not working for me (I might be applying it incorrectly).
My Enum class:
package sample;
public enum ItemType {
AUDIO("AU"),
VISUAL("VI"),
AUDIOMOBILE("AM"),
VISUALMOBILE("VM");
final String itemType;
ItemType(String itemType) {
this.itemType = itemType;
}
public String getItemType() {
return itemType;
}
}
My Controller class:
package sample;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TextField;
import java.sql.SQLException;
public class Controller {
#FXML
private TextField productName;
#FXML
private TextField productManufacturer;
#FXML
private ChoiceBox<ItemType> itemType = new ChoiceBox<>();
private DatabaseManager databaseManager = new DatabaseManager();
public Controller() throws SQLException {
}
#FXML
public void initialize() {
itemType.getItems().setAll(ItemType.values());
}
public void addProduct() {
String name = productName.getText();
String manufacturer = productManufacturer.getText();
String type = itemType.toString();
databaseManager.insert(type, manufacturer, name);
System.out.println("Button Pressed");
}
public void recordProduction(ActionEvent actionEvent) {
System.out.println("Button Pressed");
}
}
Lastly, once the ChoiceBox is populated, I need to capture the user's choice to input into my database. Something like String type = itemType.toString();.
I think you are missing the obvious and thinking the new thing, the Enum is the problem.
#FXML
private ChoiceBox<ItemType> itemType = new ChoiceBox<>();
Your controller's field has access to one ChoiceBox instance and the one on the form is a different one. You never added your items to the choicebox you interact with.
Related
I m doing a small project which manipulates a Albums of a singer, so the project provides you to add new singer to add album for specific singer and to add songs to specific album for specific singer , i m trying to get the user the chance to get the singer albums so he doesn't have to type it with his hand so I used two ComboBox one named "AvailableSinger" which clearly for available singer and the other "AlbumAvailable" for available albums for each singer, when the user select a singer the "AlbumAvailable" will display the albums of a singer selected in "AvailableSinger"
I've added two artists "Adele" and "Eminem" but when I choose Eminem the "Hello" album of "Adele" will only display.
package sample;
import MusicManiPulation.Album;
import MusicManiPulation.Singer;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import java.util.ArrayList;
public class AddSongsToAlbum {
#FXML
ComboBox<String> AvailableSinger ;
#FXML
ComboBox<Album> AlbumAvailble ;
public void initialize(){
AvailableSinger.getItems().addAll(Singer.getInstance().GetSingerNames());
AvailableSinger.getSelectionModel().selectFirst();
ArrayList<Album> AlbumList =Singer.getInstance().getAlbumNameoforSinger(AvailableSinger.getSelectionModel().getSelectedItem());
AlbumAvailble.getItems().addAll(AlbumList);
}
}
The Singer Class(in case you want to understand what I am doing)
package MusicManiPulation;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Singer {
public static Singer Instance = new Singer();
Map<String , ArrayList<Album>>AlbumListfoEachSinger ;
private Singer() {
this.AlbumListfoEachSinger = new HashMap<>();
}
public ArrayList<String> GetSingerNames(){
ArrayList<String>SingerName = new ArrayList<>();
SingerName.addAll(AlbumListfoEachSinger.keySet());
return SingerName;
}
public Map<String, ArrayList<Album>> getAlbumListfoEachSinger() {
return AlbumListfoEachSinger;
}
public ArrayList<Album> getAlbumNameoforSinger(String SingerName){
return AlbumListfoEachSinger.get(SingerName);
}
public static Singer getInstance() {
return Instance;
}
}
As you can see only the Adele albums display but when selecting another Artist it doesn't work.
First, you have to pay more attention to naming conventions in Java. Check this resource.
You can solve your problem by using one of the following methods:
Listeners:
Listeners can be added to JavaFX properties, you can add a listener that will fill the albums for a specific singer when a new singer is selected. Add this listener in your initialize method:
availableSingers.valueProperty().addListener((observable, oldSelectedSinger, newSelectedSinger) -> {
List<Album> albums = Singer.getInstance().getAlbumNameoforSinger(newSelectedSinger);
availableAlbums.getItems().setAll(albums);
});
Bindings:
you can bind the items of the albums combo box to the selected value of the singer's combo box. Add this listener in your initialize method:
availableAlbums.itemsProperty().bind(Bindings.createObjectBinding(() -> {
List<Album> albums = Singer.getInstance().getAlbumNameoforSinger(availableSingers.getValue());
return FXCollections.observableArrayList(albums);
}, availableSingers.valueProperty()));
With JavaFX, what is the best way to bind ChoiceBox to properties of a collection?
In example below I try to bind ChoiceBox elements to name of an ObservableList beans. This works fine when items are added/removed but not when the property value name change.
I was hoping there is a clean and simple solution to this but haven't yet found any example of it...
The class ExampleBean2 in deliberately not implemented with properties since that object may correspond to a external model class out of my control.
package com.playground;
import org.controlsfx.control.PropertySheet;
import org.controlsfx.property.BeanPropertyUtils;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class BindingPlayGround extends Application{
public static void main(String[] args) {
launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("FXPlayGround");
Parent content = createContentPane();
Scene scene = new Scene(content, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
protected Parent createContentPane() {
ObservableList<BeanExample2> beans = FXCollections.observableArrayList();
ObservableList<PropertySheet> sheets = FXCollections.observableArrayList();
ListView<PropertySheet> listView = new ListView<PropertySheet>(sheets);
Button addBeanButton = new Button("Add Bean");
addBeanButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
BeanExample2 e = new BeanExample2();
e.setName("Name-not-set");
PropertySheet propertySheet = new PropertySheet(BeanPropertyUtils.getProperties(e));
sheets.add(propertySheet);
beans.add(e);
}
});
VBox vBar = new VBox();
vBar.getChildren().add(listView);
vBar.getChildren().add(addBeanButton);
ObservableList<BeanExample2> names = FXCollections.observableArrayList(new Callback<BeanExample2, Observable[]>() {
#Override
public Observable[] call(BeanExample2 param) {
return new Observable[]{new SimpleStringProperty(param, "name")};
}
});
Bindings.bindContent(names, beans);
Button addChoiceBoxButton = new Button("Add ChoiceBox");
addChoiceBoxButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
ChoiceBox<BeanExample2> choiceBox = new ChoiceBox<BeanExample2>(names);
vBar.getChildren().add(choiceBox);
}
});
vBar.getChildren().add(addChoiceBoxButton);
return vBar;
}
static class BeanExample2 {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "BeanExample2{" +
"name='" + name + '\'' +
'}';
}
}
}
Here
ObservableList<BeanExample2> names = FXCollections.observableArrayList(new Callback<BeanExample2, Observable[]>() {
#Override
public Observable[] call(BeanExample2 param) {
return new Observable[]{new SimpleStringProperty(param, "name")};
}
});
you're creating a new property to listen to for updates that cannot be referenced except from the value returned by the call method. The only relationship between the BeanExample2 instance and the SimpleStringProperty is that the BeanExample2 instance is used as bean for the property, which has no effect besides being available via the getBean() method of the property. The value of the property is never assigned let alone modified on a change of the BeanExample2 instance.
To properly trigger updates in the ObservableList, you need to make sure the element in the array returned by the above method is actually notified of updates. Usually you add the property to the class itself:
public static class BeanExample2 {
public final String getName() {
return this.name.get();
}
private final StringProperty name = new SimpleStringProperty();
public final void setName(String value) {
this.name.set(value);
}
#Override
public String toString() {
return "BeanExample2{"
+ "name='" + name.get() + '\''
+ '}';
}
public final StringProperty nameProperty() {
return this.name;
}
}
And return an array containing the property from the Callback
ObservableList<BeanExample2> names = FXCollections.observableArrayList(new Callback<BeanExample2, Observable[]>() {
#Override
public Observable[] call(BeanExample2 param) {
return new Observable[]{param.nameProperty()};
}
});
Note that currently there seems to be a bug in ChoiceBox that adds entries for every intermediate value to the ChoiceBox.
ComboBox does not have this issue and could be used instead of a ChoiceBox.
For what I am doing, I need to set the members of a javafx.scene.control.ComboBox to the members of a Map#keySet() Set.
The options available in the ComboBox need to update as the keys of the Map are updated. (Basically, I want to use the ComboBox to select members from the Map, which WILL be updated at runtime.)
Unfortunately, neither ComboBox#itemsProperty().bind(ObservableValue<>) nor ComboBox#itemsProperty().set(ObservableList<>) will take a Set<>, so the direct route of connecting the itemsProperty to the Map#keySet doesn't work.
Basically:
How can I make it so the ComboBox's items are the members of a Map's keySet?
Again, the behavior that I need is that the ComboBox's items will reflect the KeySet of my Map. (The Map can be any implementation of Map.)
EDIT: The problem seems to be creating an ObservableList out of a Collection -- in this case a Set -- without making it just a copy, but rather a reference to the Set, in order that the ObservableList will reflect the Set's contents.
If you have an ObservableMap, you can add a listener to it. For example:
ComboBox<String> comboBox = ... ;
ObservableMap<String, Something> map = ... ;
map.addListener((MapChangeListener.Change<? extends String, ? extends Something> c) ->
comboBox.getItems().setAll(map.keySet()));
You can also do this with a binding, though I don't think it's any cleaner:
comboBox.itemsProperty().bind(Bindings.createObjectBinding(() ->
FXCollections.observableArrayList(map.keySet()),
map);
Here's a SSCCE, demonstrating both techniques:
import java.util.concurrent.atomic.AtomicInteger;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class BindItemsToKeySet extends Application {
#Override
public void start(Stage primaryStage) {
ObservableMap<Integer, Item> itemLookupById = FXCollections.observableHashMap();
ComboBox<Integer> listenerCombo = new ComboBox<>();
ComboBox<Integer> bindingCombo = new ComboBox<>();
itemLookupById.addListener((MapChangeListener.Change<? extends Integer, ? extends Item> c) ->
listenerCombo.getItems().setAll(itemLookupById.keySet())
);
bindingCombo.itemsProperty().bind(Bindings.createObjectBinding(() ->
FXCollections.observableArrayList(itemLookupById.keySet()),
itemLookupById));
TextField textField = new TextField();
textField.setOnAction(e -> {
if (textField.getText().isEmpty()) {
return ;
}
Item item = new Item(textField.getText());
itemLookupById.put(item.getId(), item);
textField.clear();
});
textField.setTooltip(new Tooltip("Type an item name and press enter"));
VBox root = new VBox(10,
textField,
listenerCombo,
bindingCombo);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 250, 350));
primaryStage.show();
}
public static class Item {
private final int id ;
private final String name ;
private final static AtomicInteger nextID = new AtomicInteger(1000);
public Item(String name) {
this.id = nextID.incrementAndGet();
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
launch(args);
}
}
I have a problem when it comes to filling a javafx tableview.
I am currently working on a GUI based event management tool (for university) and I am stuck trying to fill a Tableview list, that should be in the center of a border pane layout.
This is my code (its pretty long thought, its the main window function):
import java.sql.Date;
import java.sql.SQLException;
import java.util.List;
//--main imports--//
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Label;
//--table imports--//
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.TableColumn;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class MainWindow extends Application {
private static Label tableHeadline;
private static TableView table;
private static TableColumn dateCol;
private static TableColumn nameCol;
private static TableColumn numberOfGuestsCol;
private static TableColumn locationCol;
private static BorderPane layout;
//This is just some test data, this is where the program crashes, I think
final static ObservableList<Event> data = FXCollections.observableArrayList(
new Event("Jacob", "Smith", 30, new Date(10000))
);
//----------------------//
//--Private constants--//
private static final String DATE = "Date";
private static final String NAME = "Name";
private static final String NUMBER_OF_GUESTS = "Number of guests";
private static final String LOCATION = "Location";
//---------------------//
/**The main method, launching the application*/
public static void main(String[] args) {
try {
//--launching the application with given arguments--//
launch(args);}
catch (Exception e) {e.printStackTrace();}
}
/**
* The start-method, that is called first when 'launch' is used
*/
#Override
public void start(Stage primaryWindow) throws Exception {
//--initialize all the objects in the window--//
initializeObjects();
//--get the layout--//
initializeLayout();
//--give functionality to the objects in the window--//
functionalizeObjects();
//--create the new scene--//
Scene main = new Scene(layout);
//--Giving the main window a title and bringing it up front--//
primaryWindow.setMinHeight(DEFAULT_WIN_HEIGHT);
primaryWindow.setMinWidth(DEFAULT_WIN_WIDTH);
primaryWindow.setScene(main);
primaryWindow.show();
//TODO: on window close, save the content of the list to the db
primaryWindow.setOnCloseRequest(null);
}
/**
* Initializes all given elements of the main window by creating and naming them
*/
private static void initializeObjects () {
//--table--//
tableHeadline = new Label (TABLE_HEAD);
tableHeadline.setFont(new Font ("Arial", 20));
table = new TableView<>();
table.setEditable(true);
//--date column--//
dateCol = new TableColumn<Event, Date>(DATE);
dateCol.setCellFactory(
new PropertyValueFactory<>("Date")
);
//--name column--//
nameCol = new TableColumn<Event, String>(NAME);
nameCol.setCellValueFactory(
new PropertyValueFactory<>("name")
);
//--numberOfGuests column--//
numberOfGuestsCol = new TableColumn<Event, Integer>(NUMBER_OF_GUESTS);
numberOfGuestsCol.setMinWidth(150);
numberOfGuestsCol.setCellValueFactory(
new PropertyValueFactory<>("Number of Guests")
);
//--location column--//
locationCol = new TableColumn<Event, String>(LOCATION);
locationCol.setCellValueFactory(
new PropertyValueFactory<>("location")
);
table.setItems(data);
table.getColumns().addAll(nameCol,locationCol,
numberOfGuestsCol,dateCol);
//TODO fill with data from the database
//--end table--//
}
/**
* Assign functionality to the elements of the main window
*/
private static void functionalizeObjects () {
//--new... MenuItem--//
newMItem.setOnAction(e -> {
createReturn = CreatePopup.display();
if (createReturn) {
//--get the user input--//
List<Object> toCreate = CreatePopup.getInput();
//--add a new event according to the user input to the list--//
//This is where new Events should be inserted, but I cannot test this as I do not come that far
final ObservableList<Event>data = FXCollections.ObservableArrayList(
new Event(toCreate(0),toCreate(1),toCreate(2),toCreate(3))
);
}
}
});
});
}
/**
* Initializes the layout of the main window
*/
private static void initializeLayout() {
//--Create a new layout--//
layout = new BorderPane();
layout.setTop(menuBar);
layout.setCenter(table);
}
public static class Event {
private final SimpleStringProperty name;
private final SimpleStringProperty location;
private final SimpleIntegerProperty numberOfGuests;
private final SimpleObjectProperty<Date> date;
private Event(String name, String location, int numOfGuests, Date date) {
this.name = new SimpleStringProperty(name);
this.location = new SimpleStringProperty(location);
this.numberOfGuests = new SimpleIntegerProperty(numOfGuests);
this.date = new SimpleObjectProperty<Date>(date);
}
//--------//
// Getter //
//--------//
public SimpleStringProperty getName() {
return name;
}
public SimpleStringProperty getLocation() {
return location;
}
public SimpleIntegerProperty getNumberOfGuests() {
return numberOfGuests;
}
public SimpleObjectProperty<Date> getDate() {
return date;
}
}
}
This code will give me an error:
Exception in Application start method
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: javafx.scene.control.TableColumn cannot be cast to javafx.scene.control.TableColumn$CellDataFeatures
at javafx.scene.control.cell.PropertyValueFactory.call(PropertyValueFactory.java:98)
at com.sun.javafx.scene.control.skin.TableRowSkin.getCell(TableRowSkin.java:87)
at com.sun.javafx.scene.control.skin.TableRowSkin.getCell(TableRowSkin.java:53)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.createCell(TableRowSkinBase.java:698)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.recreateCells(TableRowSkinBase.java:692)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.init(TableRowSkinBase.java:146)
at com.sun.javafx.scene.control.skin.TableRowSkin.<init>(TableRowSkin.java:64)
at javafx.scene.control.TableRow.createDefaultSkin(TableRow.java:212)
at javafx.scene.control.Control.impl_processCSS(Control.java:859)
at javafx.scene.Parent.impl_processCSS(Parent.java:1272)
at javafx.scene.Parent.impl_processCSS(Parent.java:1272)
at javafx.scene.Parent.impl_processCSS(Parent.java:1272)
at javafx.scene.control.Control.impl_processCSS(Control.java:855)
at javafx.scene.Node.processCSS(Node.java:9056)
at javafx.scene.Node.processCSS(Node.java:9049)
at javafx.scene.Scene.doCSSPass(Scene.java:545)
at javafx.scene.Scene.access$3600(Scene.java:159)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2392)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$31(Toolkit.java:348)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:347)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:374)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$405(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$50(GtkApplication.java:139)
at java.lang.Thread.run(Thread.java:745)
I cannot think of any reason for this strange Error. I also searched pretty long now and tried pretty many things, but it still appears on startup.
Now I am counting on you, community, please help me!
Thanks in advance for reading the long post..
You have
dateCol.setCellFactory(...);
instead of
dateCol.setCellValueFactory(...);
This is a good example of why you should not use raw types in your code, and should avoid API like PropertyValueFactory in favor of typesafe code.
I.e. you have
TableView table ;
TableColumn dateCol ;
when you should have something like
TableView<Event> table ;
TableColumn<Event, Date> dateCol ;
And then you can do
dateCol.setCellValueFactory(cellData -> cellData.getValue().getDate());
If you coded it this way, the compiler would have immediately picked up on your error.
As an aside (perhaps, another aside), you should really make your Event class follow the correct JavaFX Properties pattern, as described in the tutorial. You may see unexpected behavior if you don't.
For the future people and Java 11 you can may fix this with that:
For example, if the Person class is in the com.foo package in the foo.app module, the module-info.java might look like this:
module foo.app {
opens com.foo to javafx.base;
}
or:
module foo.app {
opens com.foo; <-- place for with your class
}
https://openjfx.io/javadoc/11/javafx.controls/javafx/scene/control/cell/PropertyValueFactory.html
I get a nullpointerxception when following this tutorial:
Populate a tableview using database in JavaFX .
I modified it to make it simpler and fit my needs:
Instead of Usermaster, I have Person object.
while(rs.next()){
Person per = new Person();
per.ClientID.set(rs.getInt(1));
per.FirstName.set(rs.getString(2));
per.LastName.set(rs.getString(3));
The code stops at per.ClientID.set(rs.getInt(1)); due to nullpointerxception.
If I make system.out.println(rs.getInt(1)) (or any other column), I get the value... But it appears that I can't pass it to my object per.
All Person object vars are SimpleString/IntergerProperty type, as shown in the tutorial.
Can someone help me to identify the mistake I made in coding this?
Thank you
**Answer: need to initialize values.
Now I have no errors, but my table is not populating...
Full code:
a) Main App
package tableview;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MainApp extends Application {
public static void main(String[] args) {
// TODO Auto-generated method stub
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("view/FXMLTable.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Model Class:
package tableview.model;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Person {
public SimpleIntegerProperty ClientID = new SimpleIntegerProperty();
public SimpleStringProperty FirstName = new SimpleStringProperty();
public SimpleStringProperty LastName = new SimpleStringProperty();
public SimpleIntegerProperty getClientID() {
return ClientID;
}
public SimpleStringProperty getFirstname() {
return FirstName;
}
public SimpleStringProperty getLastName() {
return LastName;
}
public IntegerProperty clientIDProperty(){
return ClientID;
}
public StringProperty firstNameProperty(){
return FirstName;
}
public StringProperty lastNameProperty(){
return LastName;
}
}
Controller Class:
package tableview.view;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import tableview.model.Person;
public class FXMLTableController{
#FXML
public TableView<Person> tableview ;
#FXML
private TableColumn<Person, Number> clientIdColumn;
#FXML
private TableColumn<Person, String> firstNameColumn;
#FXML
private TableColumn<Person, String> lastNameColumn;
#FXML
private void initialize() {
assert tableview != null : "fx:id=\"tableview\" was not injected: check your FXML file 'UserMaster.fxml'.";
clientIdColumn.setCellValueFactory(cellData -> cellData.getValue().
clientIDProperty());
firstNameColumn.setCellValueFactory(cellData -> cellData.getValue()
.firstNameProperty());
lastNameColumn.setCellValueFactory(cellData -> cellData.getValue()
.lastNameProperty());
buildData();
}
private ObservableList<Person> data;
public void buildData(){
data = FXCollections.observableArrayList();
Connection con = null;
try {
Class.forName("org.sqlite.JDBC");
con = DriverManager.getConnection("jdbc:sqlite:tableviewdb.db");
String SQL = "Select * from INFO";
ResultSet rs = con.createStatement().executeQuery(SQL);
while(rs.next()){
Person per = new Person();
per.ClientID.set(rs.getInt("CLIENTID"));
per.FirstName.set(rs.getString("FIRSTNAME"));
per.LastName.set(rs.getString("LASTNAME"));
data.add(per);
}
tableview = new TableView<Person>();
tableview.setItems(data);
System.out.println(tableview.getItems().get(1).ClientID);
}
catch(Exception e){
e.printStackTrace();
System.out.println("Error on Building Data");
}
}
}
ClientID is null. You didn't initialize it.
If it's a property, you should create the proper getter and setters for it and not use the property directly. Besides you should never use 1, 2, etc in the ResultSet's getter. It's better practice to use the column names.