JavaFX8: How to create listener for selection of row in Tableview? - javafx

I currently have two tableviews in one screen, which results in both TableViews have rows which the user can select.
Now I want only one row to be selected at the same time (doesn't matter which TableView it is selected from). I was thinking about some kind of listener which deselects the other row when a row is selected. This is my initial setup:
Step 1
Search for a way to bind a method to the selection of a row (there is not something like tableview.setOnRowSelected(method))
Step 2
Create the method which acts like a kind of listener: when a row is selected, deselect the other row (I know how to do this part)
Class1 selectedObject1 = (Class1)tableview1.getSelectionModel().getSelectedItem();
Class2 selectedObject2 = (Class2)tableview2.getSelectionModel().getSelectedItem();
if(selectedObject1 != null && selectedObject2 != null) {
tableview1.getSelectionModel().clearSelection();
}
So, step one is the problem. I was thinking of an observable list on which a listener can be created, and then add the selected row to the list. When this happens, the listener can call the method.
Anyone any clue how to make this?
Any help is greatly appreciated.

The selectedItem in the selection model is an observable property, so you should be able to achieve this with:
tableview1.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
if (newSelection != null) {
tableview2.getSelectionModel().clearSelection();
}
});
tableview2.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
if (newSelection != null) {
tableview1.getSelectionModel().clearSelection();
}
});

My solution would be creating custom cell factory for table and set it for each table columns.
Callback<TableColumn<..., ...>, TableCell<..., ...>> value = param -> {
TextFieldTableCell cell = new TextFieldTableCell<>();
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, event -> {
//your code
}
);
return cell;
};
packageName.setCellFactory(value);
table1.column1.setCellFactory();
table2.column1.setCellFactory();
...

I use it for deleting the chosen row.
public void ButtonClicked()
{
ObservableList<Names> row , allRows;
allRows = table.getItems();
row = table.getSelectionModel().getSelectedItems();
row.forEach(allRows::remove);
}

This question helped me but during experiment in javafx and jfoenix this also works for me.
deleteSingle.addEventHandler(MouseEvent.MOUSE_CLICKED, (e) -> {
StringProperty selectedItem = table.getSelectionModel().getSelectedItem().getValue().link1;
System.out.println("That is selected item : "+selectedItem);
if (selectedItem.equals(null)) {
System.out.println(" No item selected");
} else {
System.out.println("Index to be deleted:" + selectedItem.getValue());
//Here was my database data retrieving and selectd
// item deleted and then table refresh
table.refresh();
return;
}
});

In case you need not only the row, but the x|y position of the table cell, do this:
table.getFocusModel().focusedCellProperty().addListener(
new ChangeListener<TablePosition>() {
#Override
public void changed(ObservableValue<? extends TablePosition> observable,
TablePosition oldPos, TablePosition pos) {
int row = pos.getRow();
int column = pos.getColumn();
String selectedValue = "";
if (table.getItems().size() > row
&& table.getItems().get(row).size() > column) {
selectedValue = table.getItems().get(row).get(column);
}
label.setText(selectedValue);
}
});
In this example, I am using a "classic" TableView with List<String> as column model. And, of course, that label is just an example from my code.

Related

How to pass a datasource of a tempTable data to a class

I have a form with a grid of a tempTable. One of the columns in the grid displays the 'existsAlready' property:
FM_MovieTemp movie = ds.getFirst(1);
while (movie)
{
if (movie.existsAlready)
{
existingMovies = true;
}
info(movie.Title);
movie = ds.getNext();
}
if (existingMovies)
{
DialogButton Button;
Button = Box::okCancel("Test",DialogButton::No);
if (Button == DialogButton::Ok)
{
FM_MovieTemp movieBuffer = ds.getFirst(1);
FM_MoviePersistLogic::PersistToDatabase(movieBuffer);
}
}
Called function:
public static boolean PersistToDatabase(FM_MovieTemp fM_MovieTemp)
{
}
The problem with this code is that, while the movieBuffer variable is filled with the data of the selected grid rowswhen it is created before the call to PersistToDatabase, it is empty in when received in the PersistToDatabase function. Could someone explain why this is and how I should correctly supply my selected grid rows to the other class?

TableView cell request Focus

I'm new in JavaFX and have the following issue:
I have a tableview inside a BorderPane. I want it to focus on the last row/1st column when it's loaded. I have tried the following:
requestfocus()
scrollTo()
focusModel.focus()
selectionModel.select()
What happens is that the cell I want is indeed blue (as if it was selected) but the first cell has a blue border. So, when I try to use the arrow keys, the selected cell moves to the first row.
BTW, I'm using TornadoFX.
Any ideas?
Thanks in advance!
class CashflowTab : View() {
override val root: HBox by fxml()
private val mController : CashflowController by inject()
private val mainView : MainView by inject()
// Get the buttons
private val buttonCashflow : Button by fxid("btnCashflow")
init {
// Setup the buttons
buttonCashflow.action {
setupCashflowTable()
}
}
/** Displays the TableView for the Cashflow */
private fun setupCashflowTable() {
var initialFocus = true
// List of entries for the category ComboBox
val categoryList = mController.getCashFlowCategoryList()
// Create the table
val cashTable = tableview<CashEntry>(mController.getCashEntryList()) {
isEditable = true
column(Constants.COL_COUNT, CashEntry::countProperty)
column(Constants.COL_DATE, CashEntry::dateProperty).makeEditable(LocaleDateConverter())
column(Constants.COL_INCOME, CashEntry::incomeProperty).makeEditable(CurrencyConverter())
column(Constants.COL_EXPENSES, CashEntry::expensesProperty).makeEditable(CurrencyConverter())
column(Constants.COL_PROFIT, CashEntry::profitProperty).converter(CurrencyConverter())
column(Constants.COL_TOTAL_PROFIT, CashEntry::totalProfitProperty).converter(CurrencyConverter())
column(Constants.COL_COMMENTS, CashEntry::commentsProperty).makeEditable()
column(Constants.COL_CATEGORY, CashEntry::categoryProperty).useComboBox(categoryList)
// Scroll to and focus on the last cell on startup
if (initialFocus) {
val lastRow = mController.getCashEntryList().size - 1
requestFocus()
scrollTo(lastRow)
focusModel.focus(lastRow)
selectionModel.select(lastRow)
initialFocus = false
}
onEditCommit {entry ->
// Update the list
mController.updateCashEntryList(entry)
// Move to the next cell
requestFocus()
focusModel.focusRightCell()
#Suppress("UNCHECKED_CAST")
selectionModel.select(focusModel.focusedCell.row, focusModel.focusedCell.tableColumn as TableColumn<CashEntry, *>)
}
enableCellEditing()
// Enable edit on key typed
addEventHandler(KeyEvent.KEY_PRESSED) {keyEvent ->
if (keyEvent.code.isDigitKey || keyEvent.code.isLetterKey) {
if (editingCell == null) {
val currentSelectedCell = selectedCell
if (currentSelectedCell != null && currentSelectedCell.tableColumn.isEditable) {
edit(currentSelectedCell.row, currentSelectedCell.tableColumn)
}
}
}
}
}
// Add the table to the view
mainView.root.center = cashTable
cashTable.tableMenuButtonVisibleProperty()
// Ensure no other node can get focus
cashTable.focusedProperty().onChange {
val focusOwner = currentStage?.scene?.focusOwnerProperty()?.value
// Check if the focus owner is the table or a cell
if (focusOwner !is TableView<*> && focusOwner !is TextField) {
cashTable.requestFocus()
}
}
}
}
You should use
Platform.runLater(() -> {
requestFocus();
scrollTo(lastRow);
...
});
to update the GUI.

bindings : count number of true booleanproperty in an observable list

i have this TableView of tasks that has a column of checkboxes. i've managed to extract the column values using stream().map(). i want to count the true values in that list.
ObservableList<BooleanProperty> list = FXCollections.observableArrayList(tasksTable.getItems().stream().map(t -> t.completedProperty()).collect(Collectors.toList()));
and another integer property
SimpleIntegerProperty count = new SimpleIntegerProperty(0);
i want this count value to be updated to the total number of true values in the list. how can i do this. i tried binding it like this
IntegerBinding count = Bindings.createIntegerBinding(() -> {
return (int)list.stream().filter(done -> done.get()).count();
}, list);
and added a listener to monitor for changes.
count.addListener((o, oldValue, newValue) -> {
System.out.println('value changed ' + newValue);
});
but its not working... nothing gets printed when i click on any checkbox...
You binding doesn't update, if the BooleanPropertys in the list change, only when the list itself is modified. You can specify conditions that trigger update changes using the correct observableArrayList method.
Example
// update triggers every time a BooleanProperty in the list is changed
ObservableList<BooleanProperty> list = FXCollections.observableArrayList((Callback<BooleanProperty, Observable[]>) e -> new Observable[] {e});
list.add(new SimpleBooleanProperty(false));
IntegerBinding trueNum = Bindings.createIntegerBinding(() -> (int) list.stream().map(BooleanProperty::get).filter(b -> b).count(), list);
trueNum.addListener((a, b, c) -> {
System.out.println(c);
});
System.out.println(trueNum.get());
list.get(0).set(true);
list.add(new SimpleBooleanProperty(false));
list.add(new SimpleBooleanProperty(true));
list.get(2).set(false);
The output is
0
1
2
1
This has the drawback of reevaluating the whole list every time one of the properties changes or the list is modified. You can do this more efficiently, if you use a ListChangeListener and register change listeners to all of the properties contained in the list:
ObservableList<BooleanProperty> list = FXCollections.observableArrayList();
...
SimpleIntegerProperty count = new SimpleIntegerProperty();
ChangeListener<Boolean> changeListener = (observable, oldValue, newValue) -> {
// increment or decrement if value was changed to true or false respecively
count.set(count.get()+ (newValue ? 1 : -1));
};
// get initial value and register change listeners to elements of list
int currentCount = 0;
for (BooleanProperty p : list) {
if (p.get()) {
currentCount++;
}
p.addListener(changeListener);
}
count.set(currentCount);
list.addListener((ListChangeListener.Change<? extends BooleanProperty> c) -> {
int modification = 0;
while (c.next()) {
// remove listeners from all properties removed in change
// and calculate update of value
for (BooleanProperty p : c.getRemoved()) {
p.removeListener(changeListener);
if (p.getValue()) {
modification--;
}
}
// add listeners from all properties added in change
// and calculate update of value
for (BooleanProperty p : c.getAddedSubList()) {
p.addListener(changeListener);
if (p.getValue()) {
modification++;
}
}
}
// update count
count.set(count.get()+modification);
});
Your lambda is called only once. You specify dependency list but uses tasksTable.getItems() In lambda-extractor you should use only values you specify as dependencies.
Also take a look at EasyBind library.

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 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.

Resources