JTable stop cell editing without user click - java

I'm trying to solve a strange problem with my program. This program creates a series of GUI's and JTables that give a user the ability to generate an XML file. One of these tables is for creating the "statements". I won't get into detail as far as that except to say that the data is stored in multiple 2D arrays which are in turn stored in a hash map.
Here is what happens. When a user enters the Statement screen a JTable is generated using the contents from the 2D array. This data populates the cell's which the user is able to modify. One of these cells (and the most important) is the amount. The amounts they set for the rows much match another amount from another class.
At the bottom of the table is a "finished" button. When the user clicks this button the logic will check to see if the money amounts match. If they do then the program will update the 2D array with any changed values and dispose of the JTable.
My problem is that once a user updates a cell and clicks "finished" the last updates made do not work. Essentially the user must first click somewhere else in the table and THEN hit finished. I would like this action to happen automatically so that when the user clicks "finished" cell editing is stopped. Here is the code for the finished button:
finishedButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
//Creates another table model for the finished button logic.
DefaultTableModel dm = (DefaultTableModel)StatementGUI.tbl.getModel();
//Gets the total number of table rows.
int rows = dm.getRowCount();
//Creates a variable to store the statement transaction total.
double statementTransactionTotal=0;
//For each row in the table.
for(int i = 0; i < dm.getRowCount(); i++){
//Gets the total of all transactions in the table.
String currentTotal = tbl.getValueAt(i, 3).toString();
Double currentTotalDouble = Double.parseDouble(currentTotal);
statementTransactionTotal=statementTransactionTotal+currentTotalDouble;
}
//Creates a decimal format and applies the statement total.
DecimalFormat df = new DecimalFormat("0.00");
String currentTotalDF = df.format(statementTransactionTotal);
//Stops editing on the table so that the data can be used.
if(null != tbl.getCellEditor()){
tbl.getCellEditor().stopCellEditing();
}
//If the statement total matches the transaction total..
if(currentTotalDF.matches(ClearedMainGUI.currentTransactionAmount)){
//For each row in the table..
for(int i = 0; i < dm.getRowCount(); i++){
//Will replace the hash/array value with the table value.
ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][0]=tbl.getValueAt(i, 0).toString();
ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][1]=tbl.getValueAt(i, 1).toString();
ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][2]=tbl.getValueAt(i, 2).toString();
ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][3]=tbl.getValueAt(i, 3).toString();
ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][4]=tbl.getValueAt(i, 4).toString();
ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][5]=tbl.getValueAt(i, 5).toString();
ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][6]=tbl.getValueAt(i, 6).toString();
ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][7]=tbl.getValueAt(i, 7).toString();
}
//For each row in the table..
for(int i = rows - 1; i >=0; i--){
//Removes the current row so the table will be empty next time.
dm.removeRow(i);
}
//Removes the frame and goes back to the previous GUI.
frame.dispose();
//If the statement total and transaction total do not match..
}else{
JOptionPane.showMessageDialog(null, "The statement total entered: $"+statementTransactionTotal+" " +
"does not match the transaction total of: $"+ClearedMainGUI.currentTransactionAmount);
}
}
});
I think my problem is with this line:
if(null != tbl.getCellEditor()){
tbl.getCellEditor().stopCellEditing();
}
This only seems to work once the user has clicked another area of the table after editing a cell.
I appreciate the help!

My problem is that once a user updates a cell and clicks "finished" the last updates made do not work.
Check out Table Stop Editing for two approaches:
You can either:
Add code to the ActionListener:
if (table.isEditing())
table.getCellEditor().stopCellEditing();
or set a property on the table:
JTable table = new JTable(...);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
Edit:
When the user clicks finished all the cell data will be saved to a 2D array.
Why? All the data is already stored in the TableModel.
In any case you need to stop editing BEFORE you attempt to copy data from the TableModel to the Array.

Related

How to get a row count for a table that does not display all rows at once?

I have a table that when the page is fully displayed has a row count of 20 rows. However, if there is more than 20, and the user scrolls down additional rows are added. Since it only gets the initial row count, I can never find the element I'm trying to search for.
What I have right now is something along these lines.
boolean isFound = false;
List<WebElement> rowList = webdriver.findElements(By.xpath("//*[contains(#class, 'requestRow')]"));
int rowCount = rowList.size();
String rowNum = null;
for (int i = 1; i <=rowCount+1; i++){
rowNum = Integer.toString(i);
}
Any idea of how I can have the table expanded and capture the new value?
OK, so what I did was create a list based on the current row count.
I then loop through the list incrementing one each time. If the number I'm looking for is found in the table, it does what I need doing. If it gets to a number higher than the current count of rows, I click the load more button, add the new value to my row count, and keep searching.

JTable getModel().setValueAt removing first element from array

I'm encountering an odd bug while updating the contents of a JTable. I've got a two dimensional array which is storing arrays of values to be displayed by the table (I'm only displaying one row of data at a time). When the user clicks a button, the next set of values (along with the next set of column headers) is displayed, and when the user clicks another button, it displays the previous set. The problem is that the first time I call getModel().setValueAt, on the first array in the two dimensional array, it is removed.
Here's the code that updates the JTable:
for(int i = 0; i < formattedData[displayedDataSet].length - 1; i++) {
TableColumn col = displayTable.getTableHeader().getColumnModel().getColumn(i);
col.setHeaderValue(WeatherData.WEATHER_MAP_KEYS[displayedDataSet * 5 + i]);
displayTable.getTableHeader().resizeAndRepaint();
displayTable.getModel().setValueAt(formattedData[displayedDataSet][i], 0, i);
}
for(String s: formattedData[0]) {
System.out.println(s);
}
I expect the output to be the first array in formattedData, but it is the second. However, commenting out the line with displayTable.getModel().setValueAt causes the correct result to be output. Why is this happening, and how can I update the JTable while preserving my array?

Removal of rows in table not working properly

I'm trying to remove the rows of data that are inside of my table when a button is clicked. My current code removes the row content after 1-3 presses, but I was hoping it would clear the content and then add the new content all in one press.
Here is the code I'm using...
private void newTasksActionPerformed(java.awt.event.ActionEvent evt) {
int sizeOfLL = taskLL.size();
DefaultTableModel textArea = (DefaultTableModel)jTable1.getModel();
int r = textArea.getRowCount();
for(int i = 0; i < r; i++) {
textArea.removeRow(i);
}
for (int i =0; i < sizeOfLL; i++) {
textArea.addRow(new Object[]{taskLL.get(i).index, taskLL.get(i).taskName, taskLL.get(i).taskDes, taskLL.get(i).taskStatus});
}
}
5 rows of data is shown in the jTable. After pressing the button again, two rows of data are deleted. If I press the button and 2nd time 1 row of data is left. Pressing the button a third time all rows of are removed and the next button press inserts 5 rows of data. Ideally I would want this button to always clear the row field and then add the data being inserted. Making every button press show fresh data as I have three buttons that have the exact same code but enter different data into the jTable.
You should try counting backwards from r-1 to 0. The problem is that the first row is removed, shifting the second row to that index. When you increment i, you are indexing past that row.
...
for (int i = r-1 ; i >= 0 ; i--) {
...

How to fetch checked values from check boxes in jtable?

I have JTable with name 'tableEarnings' it consist of 3 columns:
check
Earnings
Description
and a
jButton
Every cell in 'check' column have a checkbox. I need to fetch checked values of 'Earnings' and 'Description' cell from JTable and store it to a database when I click jButton
please help me
This my code for button listener:
private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {
//System.out.println("table"+tableEarnings.getModel().getRowCount());
for (int i = 0; i < tableEarnings.getModel().getRowCount()+1; i++) {
if ((Boolean) tableEarnings.getModel().getValueAt(i, 0)) {
System.out.println("Value" + tableEarnings.getValueAt(i, 1));
break;
}
}
}
There are three simple mistakes in your loop iterating over the table model:
Top bound for i variable should be row count - 1. Otherwise you will probably get an exception (i.e.: ArrayIndexOutOfBoundsException if your table model is DefaultTableModel)
If you find a true boolean value then don't break the loop. By doing this you lose all rows further than i index.
You are printing the value calling getValueAt() directly on the table (view) not the model. This might not retrieve the correct value if your table is sorted or columns were reordered. Always keep consistency. In this case you should work with the model.
For example:
private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {
TableModel model = tableEarnings.getModel();
for (int i = 0; i < model.getRowCount() - 1; i++) {
if ((Boolean) model.getValueAt(i, 0)) {
System.out.println("Value" + model.getValueAt(i, 1));
}
}
}
Now you will be able to print the values.
If everything goes well you have the basis now to insert the rows in your database. But be aware that database calls are time consuming tasks and may block the Event Dispatch Thread (EDT) causing the GUI become unresponsive. The EDT is a single and special thread where Swing components creation and update take place. To avoid block this thread consider use a SwingWorker to perform database calls in a background thread and update Swing components in the EDT. See more in Concurrency in Swing lesson.

Multiple Search Results, One GUI

I am searching through an array and matching the users entered date with ones stored in the array.
The code is working fine and finds dates or gives appropriate error messages perfectly, the only issue is due to the nature of my program it leaves the possibility of multiple records having the same date.
Now, I only have one form displaying each search result in this format:
lbl txtField
lbl txtField
etc, if the date is matched, it will display the REST of the data matching the record in the text fields.
Now, how would it be possible to display every record's data that has matched a date?
My Code:
public void searchDay() {
String idInputString = JOptionPane.showInputDialog(null, "Please enter the Date you're searching for using the format: DD/MM/YYYY");
for (int i = 0, count = 0; i < orderID.length; i++) {
if (idInputString.equals(startDate[i])) {
txtOrderID.setText(orderID[i]);
txtOrderForename.setText(customerForename[i]);
txtOrderSurname.setText(customerSurname[i]);
txtOrderAddress1.setText(address1[i]);
txtOrderAddress2.setText(address2[i]);
txtOrderTown.setText(town[i]);
txtOrderCounty.setText(county[i]);
txtOrderPost.setText(postCode[i]);
txtOrderCarModel.setText(carModel[i]);
txtOrderCarReg.setText(carReg[i]);
txtOrderStartDate.setText(startDate[i]);
txtOrderStartTime.setText(startTime[i]);
txtOrderSerial.setText(serialNum[i]);
count++;
}
if(i == orderID.length - 1 && count==0){
JOptionPane.showMessageDialog(null, "Order ID Doesn't Exist", "Error!", JOptionPane.WARNING_MESSAGE);
break;
}
}
}
Thank you.
Create more text fields on the fly, or drop results into a JTable.
The final UI could have a JList at the PAGE_START of the GUI that lists the orders for a day or range, but only displays the 'order number'. Then have a JPanel that contains a group of labels and field in the CENTER to display the details of an order selected in the list.
A JTable as suggested by #Ray might be a viable alternative, but I sometimes feel the data is more complex than can be well presented in a single table row (using one row per order).

Categories