JavaFX Saving editable TableView to SQL - javafx

I have created a two column editable TableView which the user can edit and change the data thats inside each cell. Now my question is, once the user has changed some data around in each cell, how do I then save this data or print it out in a way to add to an SQL query like this example below
INSERT INTO table_name
VALUES (Value from table,Value from table,Value from table,...);
//Editable cell
PriceColumn.setCellFactory(TextFieldTableCell.forTableColumn());
PriceColumn.setOnEditCommit(
new EventHandler<CellEditEvent<NewCustomerList, String>>() {
#Override
public void handle(CellEditEvent<NewCustomerList, String> t) {
((NewCustomerList) t.getTableView().getItems().get(
t.getTablePosition().getRow())).setPrice(t.getNewValue());
}
}
);

You could do this by getting the required values and then passing them onto the DAO class to execute the query on the DB. Example follows-
PriceColumn.setOnEditCommit(
new EventHandler<CellEditEvent<NewCustomerList, String>>() {
#Override
public void handle(CellEditEvent<NewCustomerList, String> t) {
((NewCustomerList) t.getTableView().getItems().get(t.getTablePosition().getRow())).setPrice(t.getNewValue());
String newPrice = t.getNewValue();
String uniqueIdentifier = t.getRowValue().getUniqueIdentifier(); //Unique identfier is something that uniquely identify the row. It could be the name of the object that we are pricing here.
daoObj.updatePrice(newPrice, uniqueIdentifier); //Call DAO now
}
}
);
And somewhere in the deep dark jungles of DAO class,
private final String updateQuery = "UPDATE <TABLE_NAME> SET <PRICE_COLUMN> = ? WHERE <UNIQUE_COLUMN> = ?"; //If you require multiple columns to get a unique row, add them in the where clause as well.
public void updatePrice(String newPrice, String uniqueIdentifier) {
PreparedStatement ps = con.prepareStatement(updateQuery); //con is the connection object
ps.setString(1,uniqIdentifier); //if a string
ps.setString(2,newPrice); //if a string
ps.executeQuery();
}
If this is not what you were expecting, then can you please clarify your requirement?

Related

JavaFX Observable List Boolean attributes not reflected on CheckBoxes

I am trying to display a list of users on a table. I write the following code in order to complete the table, however the Boolean values are not displayed on checkboxes (they are always populated as empty / false when there are actually several that are true). As a test I an just adding a single object that I am creating "manually"
Below is the code:
TableView<User> objTable = new TableView<User>();
objTable.setEditable(true);
ObservableList<User> objList = FXCollections.observableArrayList(new User("User 1", true);
TableColumn objColumnName = new TableColumn<User, String>("Column Name");
TableColumn objColumnActive = new TableColumn<User, Boolean>("Active");
objColumnName.setCellValueFactory(new PropertyValueFactory<User, String>("DisplayName"));
objColumnActive.setCellValueFactory(new PropertyValueFactory<UserRequestVO, Boolean>("Active"));
objTable.getColumns().addAll(objColumn);
objTable.setItems(objList);
User Class
public class user
{
private String strFirstName;
private Boolean bolActive;
public Boolean getActive()
{
return this.bolActive
}
}
I also try renaming getActive function as isActive, but there were no changes
You should use properties,
In your user class, you would store your boolean as a SimpleBooleanProperty :
private SimpleBooleanProperty bolActive;
Instantiated like so : this.bolActive = new SimpleBooleanProperty(false); //Or true instead of false
Now create a getter for the property, the property value, and a setter for the property value :
public BooleanProperty bolActiveProperty(){
return bolActive;
}
public final Boolean getBolActive() {
return bolActive.get();
}
public final void setBolActive(Boolean bolActive) {
this.bolActive.set(bolActive);
}
Now when you create your table columns, you do this :
objColumnActive.setCellValueFactory(cellData -> cellData.getValue().bolActiveProperty());
Or if you prefer old school java :
objColumnActive.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<User,Boolean>, ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(CellDataFeatures<User, Boolean> cellData) {
return cellData.getValue().bolActiveProperty();
}
});
This also work I think, might be wrong though :
objColumnActive.setCellValueFactory(new PropertyValueFactory<User, Boolean>("bolActive"));
This will allow you to bind the User property to the column, so that any modification of the column will affect the value in the user.
Nice thing is you can listen to the value modification using myProperty.addListener((obs, oldV, newV) -> { /* Your code */ });
Where obs is the value observed, oldV the old value, and newV the new value (obviously)
Does that help/work for you?

Combobox selections disappear when table editing canceled

Ok, I'm starting to lose my mind on this one. I have a tableview where there are 3 combobox table cells. The first is a box where a user can select a job, the job selected changes the next combobox's options (job category). The job category selection changes the options in the labor box. So the flow down is:
job > job category > labor.
I have a very peculiar problem. When editing the table, you can click on any box to get a corresponding list of the available selections based on the other fields. This works fine. Where it blows up is when a selection ISN'T made. To make things more interesting, it only effects the job and job category comboboxes the labor box works flawlessly.
symptom:
-- job category selection disappears when edit is canceled via esc or focus lost
-- selection chosen in the job category field is placed into the job field when editing is canceled via esc or upon loss of focus
Here's the steps to recreate the symptoms:
1) click on job category box and enable editing mode
2) make a new selection from the drop down list
new selection made img
3) click on the job box and enable editing
4) click off the job box and cancel editing by click on job category or labor box in the same row
5) enable job category editing and then cancel job category edit by clicking on either labor / labor boxes or using esc
lose the job category / job selections img
here is the code to initialize the graphic when it comes up:
public void initialize(URL location, ResourceBundle resources) {
/* this is here because the screen handler will load up the Main screen in the
in the hashmap; no connection data will be assigned to the user at that time.
Without this block, when the hashmap attempts to load the Main data this
will cause the screenhandler to error and the main application
to not load correctly. The block below initiatializes the connection to
prevent this from happening.*/
if ( vUsers.getConn() == null){
try {
//establishes a user's connection to the database
vUsers.ConnecrDB();
} catch (SQLException | IOException ex) {
//debugging catch
System.out.println(ex);
}
}
//set the job box list for the user
cmbxJobT.setItems(cmbxPopulator.getJobComboBox());
cmbxJobT.valueProperty().addListener(new ChangeListener<String>(){
#Override
//reads the user's selectino and returns the appropriate labor codes for the Employee
public void changed(ObservableValue o, String oldValue, String newValue){
if (newValue != null){
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(newValue));
}else {
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().add(null);
}
}
});
cmbxJobCatT.valueProperty().addListener(new ChangeListener<String>(){
#Override
//reads the user's selectino and returns the appropriate labor codes for the Employee
public void changed(ObservableValue o, String oldValue, String newValue){
if (newValue != null){
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(newValue));
}else {
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().add(null);
}
}
});
tblviewTime.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSel) ->{
if (newSel != null){
Model_Time current = tblviewTime.getSelectionModel().getSelectedItem();
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(current.getJob()));
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(current.getJobCat()));
}
if (newSel == null){
Model_Time current = tblviewTime.getSelectionModel().getSelectedItem();
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(current.getJob()));
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(current.getJobCat()));
}
});
addDragListeners(bertaTabPane);
}
here's the code that sets up the tableview:
public void btnTimeSearch(ActionEvent event){
//makes an instance of the toolkit needed to query user time.
Database_RetrievesTime userData = new Database_RetrievesTime();
//grabs data from the userinput fields to set the toolkit
userData.setDateSelect(lblPickDateT.getValue());
userData.setJobBoxSelect(jobTbl.getIdByDesc(cmbxJobT.getValue()));
userData.setLaborBoxSelect(laborTbl.getIdByDesc(cmbxLaborT.getValue()));
userData.setJobCatSelect(jobCatTbl.getIdByDesc(cmbxJobCatT.getValue()));
/*creates cell factories in each column and maps the cell values to the
observable array list's IDs. The section also sets the columns up for user
editing to be available and the methods to execute upon an editted cell
being committed to entry.
**NOTE: The values are retrieved by the model class's getter methods.
Changing a name in the model class requires the user to update the getters.
Naming convention does apply. So for example: a variable
named cscHelp is added, it would need to have a getter called getCscHelp otherwise
the corresponding column will return blanks.*/
//setup ID column
IDcol.setCellValueFactory(new PropertyValueFactory<>("ID"));
//setup Datecol
Datecol.setCellValueFactory(new PropertyValueFactory<>("userDate"));
Datecol.setCellFactory(DatePickerTableCell.forTableColumn());
//created a custom datepicker callback that can be reused throughout the code's interfaces
Datecol.setOnEditCommit((CellEditEvent<Model_Time,LocalDate> t) -> {
//generate a temporary variable to convert the LocalDate returned into a SimpleObjectProperty
ObjectProperty<LocalDate> temp = new SimpleObjectProperty(t.getNewValue());
//store the new value to the object's model
t.getRowValue().setUserDate(temp);
//store row's object to the change list
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
//signaling to the program that a change had been made
isChanged = true;
});
//job column setup
Jobcol.setCellValueFactory(new PropertyValueFactory<>("Job"));
Jobcol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getJobComboBox()));
/*creates a combobox filled with the populated items found at initialization of the screen
user inputs are automatically commited
*/
Jobcol.setOnEditCommit((CellEditEvent<Model_Time,String> t) -> {
SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
//store selection to the object's model (unprocessed so values will show something like '6002: Kobota'
t.getRowValue().setJob(ssp);
//store row's object to the change list
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
cmbxJobCatT.getItems().clear();
cmbxJobCatT.getItems().addAll(cmbxPopulator.getJobCatComboBox(t.getRowValue().getJob()));
//signaling a change has been made
isChanged = true;
});
jobCatCol.setCellValueFactory(new PropertyValueFactory<>("JobCat"));
jobCatCol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getJobCatComboBox(cmbxJobT.getValue())));
jobCatCol.setOnEditCommit((CellEditEvent<Model_Time,String> t)->{
SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
//store selection to the object's model (unprocessed so values will show something like '6002: Kobota'
t.getRowValue().setJob(ssp);
//store row's object to the change list
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
cmbxLaborT.getItems().clear();
cmbxLaborT.getItems().addAll(cmbxPopulator.getLaborComboBox(t.getRowValue().getJob()));
//signaling a change has been made
isChanged = true;
});
//labor column setup works just like the job column
Laborcol.setCellValueFactory(new PropertyValueFactory<>("Labor"));
Laborcol.setCellFactory(ComboBoxTableCell.forTableColumn(cmbxPopulator.getLaborComboBox(cmbxJobCatT.getValue())));
Laborcol.setOnEditCommit((CellEditEvent<Model_Time,String> t) -> {
SimpleStringProperty ssp = new SimpleStringProperty(t.getNewValue());
t.getRowValue().setLabor(ssp);
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
t.getTableView().getItems().get(t.getTablePosition().getRow()).setLabor(ssp);
isChanged = true;
});
//time column setup.
Timecol.setCellValueFactory(new PropertyValueFactory<>("Time"));
Timecol.setCellFactory(TextFieldTableCell.<Model_Time, Float>forTableColumn(new FloatStringConverter()));
Timecol.setOnEditCommit((CellEditEvent<Model_Time,Float> t) -> {
//temp variable initialiation
float token = t.getNewValue();
//generate a temporary variable to convert the float return to a SimpleFloatProperty
SimpleFloatProperty temp = new SimpleFloatProperty(token);
//now update the row's object
t.getRowValue().setTime(temp);
//store row's object to the change list
Helper_TimShArrGen.addToEditedMatrix(t.getRowValue());
isChanged = true;
});
//set tableView editable
tblviewTime.setEditable(true);
//sets tableView to allow multiline selection
TableViewSelectionModel<Model_Time> tvt = tblviewTime.getSelectionModel();
tvt.setSelectionMode(SelectionMode.MULTIPLE);
/* checks if edits have been made. If there are edits, it commits to the
database before wiping the arraylists and updating the table*/
if (isChanged == true){
/*makes sure there are no duplicate entries in the arraylist. Throws out
previous edits and takes the most recent*/
Helper_TimShArrGen.validateMatrixEntries();
//commits changes and resets the "isChanged" value.
isChanged = Helper_TimShArrGen.confirmChanges(vUsers, jobTbl, jobCatTbl, laborTbl, isChanged);
}
/*tells the kit to run the querytime Method which uses the user input data
and user data to search the timesheet tables and returns the user's time.*/
if (isChanged == false){
try {
rs = userData.queryTime(vUsers.getConn(), vUsers.getLogin_ID());
} catch (SQLException ex) {
System.out.println(ex);
}
} else {
return;
}
//sets up the observablelist for the tableview
renderTable.setTableView(tblviewTime);
ObservableList n = renderTable.generateTable(jobTbl, jobCatTbl, laborTbl, rs, vUsers.getConn());
//renders the data on the screen`
tblviewTime.setItems(n);
Helper_TimeBreakDown breakdown = new Helper_TimeBreakDown();
breakdown.setTblArr(n);
breakdown.BreakDwnTim();
lblMonTim.setText(String.valueOf(breakdown.getMon()));
lblTuesTim.setText(String.valueOf(breakdown.getTues()));
lblWedsTim.setText(String.valueOf(breakdown.getWeds()));
lblThursTim.setText(String.valueOf(breakdown.getThurs()));
lblFriTim.setText(String.valueOf(breakdown.getFri()));
lblSatTim.setText(String.valueOf(breakdown.getSat()));
lblSunTim.setText(String.valueOf(breakdown.getSun()));
lblWkTim.setText(String.valueOf(breakdown.getWeek()));
}
this is the segment from the class that handles the data that goes into the lists.
public ObservableList<String> getJobComboBox(){
//clear the jobList to clean out junk data between calls
jobList.clear();
//looks at the job table to determine if the job is active. If active, it reads the entry
for (count=0; count<= jobTbl.getTblArray().size()-1; count++){
if(jobTbl.getTblArray().get(count).isActive()){
/*here we scroll through the JobIDList and match the IDs to the jobtbl
data. When a match is hit, we grab up the number on the job and the description
this is added to another array that will become the combobox's list
*/
for(inCount = 0; inCount <= jobIDList.size()-1; inCount++){
if(jobIDList.get(inCount).getCol2ID() == jobTbl.getTblArray().get(count).getID()){
jobList.add(jobTbl.getNumById(jobIDList.get(inCount).getCol2ID())
+ ": " + jobTbl.getDescById(jobIDList.get(inCount).getCol2ID()));
}
}
}
}
/* there's probably a better dataset to use that won't allow duplicates
due to my lack of knowledge at this time, I elected to create a hashset, pass the arrayList
to the hashset to wipe out duplicates, and then pass it back to the arrayList to be used in the combobox
*/
Set<String> tmp = new HashSet();
tmp.addAll(jobList);
jobList.clear();
jobList.addAll(tmp);
jobList.add(null);
return jobList;
}
/**
*
* #param job Argument for the selected Job String
* #return returns the ObservableList of strings for the Job Category ComboBox
*/
public ObservableList<String> getJobCatComboBox(String job){
//clearing out old artifact data from the previous selection
jobCatList.clear();
//splitting the user's string selection apart (number as string, description as string)
int jID=0;
if (job != null){
if (job.contains(": ")){
String[] tmp = job.split(": ");
job = tmp[1];
}
}
// here we comb the job Table for a matching description and vacuum up the associated ID number
for(count=0; count<=jobTbl.getTblArray().size()-1; count++){
if(jobTbl.getTblArray().get(count).getDesc().equals(job)){
jID = jobTbl.getTblArray().get(count).getID();
}
}
/*using that jobID number to examine the fKey in the category table.
once we match the JobID to the fKey ID in the jobCat table, we scoop up the
the job Category code and description to create a list for the combobox
*/
for (count=0; count<= jobCTbl.getTblArray().size()-1; count++){
for(inCount = 0; inCount <= jobCatIDList.size()-1; inCount++){
if(jobCatIDList.get(inCount).getID() == jobCTbl.getTblArray().get(count).getID()){
if(jobCTbl.getTblArray().get(count).getfKeyId() == jID){
jobCatList.add(jobCTbl.getNumById(jobCatIDList.get(inCount).getID())
+ ": " + jobCTbl.getDescById(jobCatIDList.get(inCount).getID()));
}
}
}
}
//same house keeping to remove duplicates as described above
Set<String> tmp = new HashSet();
tmp.addAll(jobCatList);
jobCatList.clear();
jobCatList.addAll(tmp);
jobCatList.add(null);
return jobCatList;
}
/**
*
* #param jobCat Argument for the selected Job Category String
* #return ObservableList of strings for the Labor ComboBox
*/
public ObservableList<String> getLaborComboBox(String jobCat){
//temp arrays I needed to decode the affiliated connections
ArrayList<Integer> jCID = new ArrayList();
ArrayList<Integer> laborID = new ArrayList();
//house keeping to remove artifact data from previous selections
if(jCID != null){
jCID.clear();
}
if(laborID != null){
laborID.clear();
}
if(laborList !=null){
laborList.clear();
}
//split user's string selection for the job category (numerical code as sting, description as string)
if(jobCat != null){
if (jobCat.contains(": ")){
String[] tmp = jobCat.split(": ");
jobCat = tmp[1];
}
}
//use the description to find the affiliated job category ID
for(count=0; count<=jobCTbl.getTblArray().size()-1; count++){
if(jobCTbl.getTblArray().get(count).getDesc().equals(jobCat)){
jCID.add(jobCTbl.getTblArray().get(count).getID());
}
}
//use the job category ID to find the associated labor IDs from the associate entity table
for(count=0; count<=jCLTbl.getTblArray().size()-1; count++){
for(inCount=0; inCount<=jCID.size()-1; inCount++){
if(jCLTbl.getTblArray().get(count).getCol1ID() == jCID.get(inCount)){
laborID.add(jCLTbl.getTblArray().get(count).getCol2ID());
}
}
}
//use the labor ID to look up the needed data from the labor table.
for (count=0; count<= laborTbl.getTblArray().size()-1; count++){
for(inCount = 0; inCount <= laborID.size()-1; inCount++){
if(laborID.get(inCount) == laborTbl.getTblArray().get(count).getID()){
laborList.add(laborTbl.getNumById(laborID.get(inCount))
+ ": " + laborTbl.getDescById(laborID.get(inCount)));
}
}
}
//more housekeeping to remove duplicate entries.
Set<String> tmp = new HashSet();
tmp.addAll(laborList);
laborList.clear();
laborList.addAll(tmp);
laborList.add(null);
return laborList;
}
I know there are probably better ways to do things here. I'm still new to JAVA and coding. I work at a small company so I'm the only coder they employee. Unfortunately this limits me to what I can teach myself, so there are probably some more efficient ways to accomplish the same mission here. Anyway, if anyone could help me figure out what is going on, it would be appreciated.
The answer to this problem is actually found in the SetOnEdit portion of the jobcatCol.
upon closer inspection and a lot of debugging, I found that this line
t.getRowValue().setJob(ssp);
is actually supposed to be
t.getRowValue().setJobCat(ssp);
I also chose to forego the ComboBoxTableCell API and write my own combobox implementations for each cell. It's a very basic version found here:
public class JobComboBoxCell extends TableCell<Model_Time, String>
{
private ComboBox<String> comboBox;
private Helper_UserSpecificTimDat cmbxPopulator = new Helper_UserSpecificTimDat();
public JobComboBoxCell(Helper_UserSpecificTimDat cmbxPopulator)
{
comboBox = new ComboBox<>();
this.cmbxPopulator = cmbxPopulator;
}
#Override
public void startEdit()
{
if ( !isEmpty() )
{
super.startEdit();
comboBox.setItems( cmbxPopulator.getJobComboBox() );
comboBox.getSelectionModel().select( this.getItem() );
comboBox.focusedProperty().addListener( new ChangeListener<Boolean>()
{
#Override
public void changed( ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue )
{
if ( !newValue )
{
commitEdit( comboBox.getSelectionModel().getSelectedItem() );
}
}
} );
setText( null );
setGraphic( comboBox );
}
}
#Override
public void cancelEdit()
{
super.cancelEdit();
setText( ( String ) this.getItem() );
setGraphic( null );
}
#Override
public void updateItem( String item, boolean empty )
{
super.updateItem( item, empty );
if ( empty )
{
setText( null );
setGraphic( null );
}
else
{
if ( isEditing() )
{
setText( null );
setGraphic( comboBox );
}
else
{
setText( this.getItem() );
setGraphic( null );
}
}
}
}
This code was courtesy of Uluk Biy's response in thread:Populate combo box list dynamically for each row in javaFx table view
I adapted his code a little bit to specifically fit my needs. This solved a problem with values disappearing from the job category field and from data transferring from the job category field to the Job field.
This was one of the harder pieces of code I've had to troubleshoot. It was a combination of how the ComboBoxTableCell operates, the dynamic data of my comboboxes, and a slip in the which setter I was calling. It was about a perfect storm of flubs that the program saw no exceptions for as a result.
Thank you for the help

JavaFX Add data to Column's instead of row

Good day,
I have a fixed number of columns in TableView, however I need to populate column by column, not row by row, as one column data depends on the previous one. Is there an example of such thing? I have searched for such way, but unfortunately. Hope I made it understandable.
Since nobody provided me an example, and the comment was not very helpful I manage to solve my problem in the following way (in my case one column result depends on the previous one and the number of elements can be different as well as the number of columns are predefined)
Simple example:
We have an object:
public class Cars{
private String name;
private String company;
private String year;
public Cars(String name,String company,String year){
this.name=name;
this.company=company;
this.year=year;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company= company;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year= year;
}
}
Then we have our table:
public TableView createTable() {
TableView<Cars> table = new TableView<>();
TableColumn<Cars, String> nameyColumn = new TableColumn("Name");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
TableColumn<Cars, String> companyColumn = new TableColumn<>("Company");
companyColumn.setCellValueFactory(new PropertyValueFactory<>("company"));
TableColumn<Cars, String> yearColumn = new TableColumn<>("Year");
yearColumn.setCellValueFactory(new PropertyValueFactory<>("year"));
table.setItems(makeCars());
table.getColumns().addAll(nameColumn, companyColumn, yearColumn);
return table;
}
Afterwards we generate the information that we want to put into the table and put all the information into, in this case a String Array. So if we have 3 String arrays we can make an ArrayListlist of arrays and populate it with information.
However, the sizes of the String arrays inside the ArrayList have to be predefined, so that you would not get a NullPointException where the at one point you have a car's name and you dont have a year it will be set to an empty automatically, as an empty predefined String array contains null as elements automatically. So in my case I know the max size that one array can be and set all of them to the same size.
And afterwards I just loop through the ArrayList of String Arrays and create objects which I add to the ObservableList ( might be a better way of doing it but I did it this way):
private ObservableList<Cars> makeCars() {
ObservableList<Cars> madeList = FXCollections.observableArrayList();
ArrayList<String[]>arrayOfArrays=new ArrayList<>();
for(int i=0;i<maxRow;i++){
madeList.add(new Cars(arrayOfArrays.get(0)[i],arrayOfArrays.get(1)[i],
arrayOfArrays.get(2)[i]));
}
return madeList;
}
Hope this will helpful to somebody, if there is a better way and I am overdoing it please share.

javaFX table view couldn't update table crash when adding new rows

I have TableView with number of columns, I have set onEditCommit method on the first column to get the value inserted and then retrieve data from database based on that value and set the retrieved data in other columns. the table couldn't update it's content.
accountNoCol.setOnEditCommit(new EventHandler<CellEditEvent<Bond, String>>() {
#Override
public void handle(CellEditEvent<Bond, String> event) {
String newValue = event.getNewValue();
Bond bond = event.getRowValue();
int selectedRow = event.getTablePosition().getRow();
if (isInteger(newValue)) {
((Bond) event.getTableView().getItems().get(
event.getTablePosition().getRow())).setAccountNo(newValue);
if (isDebtAccount(newValue)) {
String accountName = getDebtAccountName(newValue);
String coinName = getCoinName(newValue);
float coinExchange = getCoinExchange(newValue);
bond.setAccountName(accountName);
bond.setCoinName(coinName);
bond.setCoinExchange(coinExchange);
bondTable.getSelectionModel().select(selectedRow, statementCol);
} else if (isNonDebtAccount(newValue)) {
String accountName = getNonDebtAccountName(newValue);
bond.setAccountName(accountName);
bond.setCoinName(getDefaultCoinName());
bond.setCoinExchange(1);
bondTable.getSelectionModel().select(selectedRow, statementCol);
}
else {
System.out.println("wrong acount name");
// show accounts table - i guess
}
} else {
if (newValue.length() == 0) {
System.out.println("length : " + newValue.length());
((Bond) event.getTableView().getItems().get(
event.getTablePosition().getRow())).setAccountNo(newValue);
}
}
}
});
I tried to use this next line but the table get crashed after adding new rows
bondData.set(selectedRow,Bond);
Solved. The problem was the table get crashed when am trying to open new stage from a listener on a tablecolumn. so on listener and before fire my action which is opening new stage i set the tablecolumn uneditable.

How to create table with dynamic amount of columns

Thare is a tutorial at javaFX documentation page. This example describes how to make tableView, if you have some sertain java class, which can tell you which columns you are going to have. (That is a Person class in this example).
But what if i do not have any specific class, and number of columns can vary from time to time?
In my case i have such data structure:
class TableData{
List<Row> rows; //A list with all my rows i need to have in my table
}
class Row{
List<Column> columns; //Cells\Columns for every row.
}
class Column{
Attribute attr; //Each column - is somethig like a wrapper for the real data i need to show in a cell;
}
class Attribute{ //My precues data
String name;
SupportingInfo info;
}
class SupportingInfo{//Some supporting fields...
String name;
String value;
//...etc....
}
So, my case is very similar to this one.
The only differents is that data from the case above is not binded with its representation in javaFX table (so, even if some one will make extra controls to edit this data in a tableView, the actual object with that data will never know about it.), because it(data) goes to the table like some strings, not like some objects;
So, what do i need - is to push data to the table (like that: table.setItems(tableData)), set some set Factories, to give user ability to edit data, and to have this edited data in my tableData object;
Here are some code ive tried to make for this purpose:
//prepare my table
private void createTableHeader(TableView table, List<Attribute> ias) {
int i = 0;
for (final Attribute ia : ias) {
final int j = i;
i++;
TableColumn tc = new TableColumn(ia.getName());
tc.setSortable(true);
tc.setCellValueFactory(new Callback<CellDataFeatures<List<Attribute>, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(CellDataFeatures<List<Attribute>, String> arg0) {
if(arg0.getValue().get(j).getSupportingInfo() == null){
arg0.getValue().get(j).setSupportingInfo(new SupportingInfo());
}
return new SimpleObjectProperty(arg0.getValue().get(j),"value");
}
});
table.getColumns().add(tc);
}
}
//loading some data to my tableView
private void createTableBody(TableView curTable, List<Row> rows) {
ObservableList<List<Attribute>> data = FXCollections.observableArrayList();
for (Row row : rows) {
data.add(row.getColumns());
}
curTable.setItems(data);
}
//this one is to define some extra controls for editing data in a table by users
private void makeCellFactory(TableColumn curTableCol, final Attribute templateIa, final Document doc) {
curTableCol.setCellFactory(new Callback<TableColumn, TableCell>() {
public TableCell call(TableColumn p) {
final EditingCell cell = new EditingCell(templateIa, doc);
return cell;
}
});
}
But, as a result, i have just empty rows in my table, with an ability to click some cell and recieve table editing controls. But there is not defult values in by table;
What am i doing wrong in my code?
Ok, i've found a solution:
ts.setCellFactory should look like this:
tc.setCellValueFactory(new Callback<CellDataFeatures<List<Attribute>, SupportingInfo>, ObservableValue<Attribute>>() {
#Override
public ObservableValue<Attribute> call(CellDataFeatures<List<Attribute>, SupportingInfo> arg0) {
return new SimpleObjectProperty(arg0.getValue().get(j),"value",arg0.getValue().get(j));
}
});
Also, this code is needed to catch new values and put the incoming data to the table:
tc.setOnEditCommit(new EventHandler<CellEditEvent<List<Attribute>, Attribute>>() {
#Override
public void handle(CellEditEvent<List<Attribute>, Attribute> t) { t.getTableView().getItems().get(t.getTablePosition().getRow()).get(j).setSupportingInfo(t.getNewValue().getSupportingInfo());
}
});

Resources