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.
Related
Hello I am working on a project with a JTable to join words. In the table words that have been joined together have an # character between them.
I basically want to remove all the rows in the table containing the character #. This is what I have tried so far:
for (int i = 0; i < table.getRowCount(); i++) {
if ((boolean)table.getValueAt(i, 0).equals("\\b[#]+\\b")) {
table.remove(i);
}
}
This code is not working as intended. I would like to know the correct way to write this code. Thank you for any replies in advance.
Your code calls the remove() method inherited from the Container class - you want to manipulate the table model used by your table. Assuming that you're using a DefaultTableModel, you can get the model from the table and use the removeRow() method.
Also, .equals("\\b[#]+\\b") doesn't check for a String containing the '#' character. It checks for an exact match of the text that you specified. You might want to look at the String.contains(...) method.
Remember that the data in a Swing JTable is stored in an underlying TableModel, not in the JTable object itself. Something like this should work.
DefaultTableModel model = (DefaultTableModel) table.getModel();
for (int i = 0; i < model.getRowCount(); i++) {
if (model.getValueAt(i, 0) != null && model.getValueAt(i, 0).toString().contains("#")) {
model.removeRow(i);
}
}
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.
I am working on a GUI that will feature a table that has been manually connected to a database. Above this table there are 3 radio buttons that will "decide " what criteria is to be used when fetching the data( All rows have a boolean value, depending on the button pressed it is supposed to return either 1, 0 or both).
This is the code for the table(NOTE i am using netbeans gui designer)
ServiceTable = new javax.swing.JTable();
int radiovalue = 0;
if (RadioActive.isSelected()) radiovalue = 0;
else if (RadioAll.isSelected()) radiovalue = 1;
else if (RadioFinished.isSelected()) radiovalue = 2;
Object[][] DataAct = null;
try {
DataAct = SQL.MYSQL_FETCH_OMNI_DATA(radiovalue);
} catch (Exception ex) {
Logger.getLogger(MainforAdmin.class.getName()).log(Level.SEVERE, null, ex);
}
String[] Colnombs = SQL.MYSQL_ROW_NOMBER();
ServiceTable.setAutoCreateRowSorter(true);
ServiceTable.setModel(new javax.swing.table.DefaultTableModel( DataAct, Colnombs ));
TableContainer.setViewportView(ServiceTable);
This works as it should and the 2 external functions return arrays that make the table display what it should display (Which is as the program starts all the "active " transactions)
However i want to be able to change the table so that it will evaluate if radioactive is equals to 0, 1 or 2 (The number is going to determined what data the function fetches). The program outputs the MYSQL tables trough System.out.print perfectly with the diffrent criterias. So I know my functions are working. But I can not figure out how I am to make the entire table "refresh" after another radiobutton is selected..
This is my event code for Mousepressed for a radio button.
TableRefresher();
System.out.println("Pressed");
And Pressed is outputed so i know this code has been summoned after clicking on the radio button. Here is the TableRefresher function.
Write.Echo("The TableRefresher method hath been summoned");
//This code is going to evaluate which button is selected as of now.
MainforAdmin table = new MainforAdmin();
if (table.RadioActive.isSelected()) radiovalue = 0;
else if (table.RadioAll.isSelected()) radiovalue = 1;
else if (table.RadioFinished.isSelected()) radiovalue = 2;
Object[][] DataAct = null; //This code is going to innitialize the tablecontents.
try {
DataAct = SQL.MYSQL_FETCH_OMNI_DATA(radiovalue);//This code assigns the table contents And i know this works because it correctly outputs the table with the diffrent where clause (where state = x or the status as you saw on the picture.)
} catch (Exception ex) {
Logger.getLogger(MainforAdmin.class.getName()).log(Level.SEVERE, null, ex);
}
String[] Colnombs = SQL.MYSQL_ROW_NOMBER(); //Assigns the column names and works is used as the table is created so this works.
table.TableContainer.remove(table.ServiceTable);
table.add(table.ServiceTable, null);
table.ServiceTable.setModel(new javax.swing.table.DefaultTableModel( DataAct, Colnombs ));
table.ServiceTable.revalidate();
table.ServiceTable.repaint();
table.TableContainer.setViewportView(table.ServiceTable);
Yet as this method is summoned(Which i know it is from the console output) nothing happens to the JTable in the GUI...It stays the same.
So how am i supposed to refresh the table after a different criteria for fetching the data has been applied ? I have looked at other suggestions here on this site but none of them worked or gave me what i needed.
Any answers would be very appreciated, and please forgive me if this is an easy question I am by no means a Programming deity.
If it makes any difference the JTable is in a Scrollpane..
Sincerly...
//Orville Nordström.
Just as a start:
If it makes any difference the JTable is in a Scrollpane.
That's correct and it must keep in this way. It makes no difference to solve the main problem though.
So how am i supposed to refresh the table after a different criteria for fetching the data has been applied?
Code quote:
table.TableContainer.remove(table.ServiceTable);
table.add(table.ServiceTable, null);
table.ServiceTable.setModel(new javax.swing.table.DefaultTableModel( DataAct, Colnombs ));
table.ServiceTable.revalidate();
table.ServiceTable.repaint();
table.TableContainer.setViewportView(table.ServiceTable);
Please note this is kind of spaghetti code and it's not clear which is the table to be updated. However the correct way to update a table is not removing / re-creating / re-locating it but working with / refreshing its table model instead. See examples here (includes SwingWorker to make database calls in a background thread), here and here. Please have a look to those answers, there are explanations to make the point clear.
Off-topic
Looking at the quoted lines above, I'd suggest you to avoid using static members. Those are intended to very specific cases (i.e.: constants) but not to general use, and often breaks the encapsulation principle. In this particular case they led to an unintelligible chain of calls that are probably wrong and causing an unexpected hard-to-debug (for us) behavior.
if I understand your problem is that you can not "refresh" the table, in my programs I use this method (DefaultTableModel):
private void jButtonActionPerformed(java.awt.event.ActionEvent evt) { .......
..................
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object[][]{},
new String[]{
"CLMN1", "CLMN2", "CLMN3", "CLMN..."
}) {});
enter code here
model = (DefaultTableModel) jTable.getModel();
model.addRow(new Object[]{("YOUR ROW"}); ----> in a While(or FOR), for any rows
bye :)
I have a JTable displaying contents in this format:
Part Number Quantity Price
SD1131 7 1,000
SD6534 6 2,000
On the same frame I have a JTextfield(txtNo). I need it such that when the user types the Part Number on the JTextfield, the corresponding record is selected on the JTable. So far I have only been able to select records based on the row number like this:
txtNo.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
int index1 = 0;
int index2 = 0;
try {
index1 = Integer.valueOf(txtNo.getText());
tbStore.setRowSelectionInterval(index2, index1);
} catch (Exception ae) {
ae.printStackTrace();
}
}
});
How can I implement the same method to select the JTable row based on the input of the JTextfield?
You will need to find the item in your table for which the part number is equal to the part number entered in the textfield. Steps to take:
Read the contents of your textfield
Search the index of the matching element in the TableModel
Convert that index to the corresponding row index in the JTable using the convertRowIndexToView method (to take in account sorting, filtering, ... )
Use the setRowSelectionInterval method of the JTable to select that row
As an alternative, you can use the JXTable of the SwingX project which has searching capabilities built-in. The SwingX library also includes a component which allows to search such a JXTable (see JXSearchPanel and JXSearchField)
You should interrogate the TableModel and find out which row contains the part number you are looking for:
for(int i=0;i<tbStore.getRowCount();i++) {
// 0 is for the column Part number
if(tbStore.getValueAt(i, 0).equals(Integer.valueOf(txtNo.getText())) {
tbStore.setRowSelectionInterval(i, i);
break;
}
}
Caveats: I haven't tested this code, but it should give you at least the basic idea.
I'm having difficulties getting the following code to preserve the logically selected row in the model if the JTable has been sorted.
It works as intended when no sorting is applied.
private void updateAccountTable() {
accountsTable = guiFrame.getAccountsTable();
// Preserve selected model row
String accountNumber = "";
int selectedRow = accountsTable.getSelectedRow();
if(selectedRow >= 0){
accountNumber = (String)accountsTable.getValueAt(selectedRow, 0);
}
// Preserve sort order
// Keep eclipse happy. better way??
List <? extends SortKey> keys = accountsTable.getRowSorter().getSortKeys();
// Update displayed accounts
DefaultTableModel model = (DefaultTableModel) accountsTable.getModel();
model.getDataVector().clear();
Object[][] tableContents = accountList.getAccountsAsArray(true);
model.setDataVector(tableContents, tableHeaders);
model.fireTableDataChanged();
// reset sort order
accountsTable.getRowSorter().setSortKeys(keys);
// If updated model contains previously selected account, reselect
if (!accountNumber.equals("") && null != accountList.getAccount(accountNumber)){
for (int row=0; row<accountsTable.getRowCount(); row++){
String an = (String)accountsTable.getValueAt(row, 0);
if (an.equalsIgnoreCase(accountNumber)){
accountsTable.setRowSelectionInterval(row, row);
break;
}
}
}
else {
accountsTable.clearSelection();
}
}
Unfortunately setRowSelectionInterval() doesn't updated the selected row as expected, despite being called with the correct view row number. It seems to do nothing.
.....So,
Why is setRowSelectionInterval() failing to updated the selection, or what have I missed?
The row obtained from getSelectedRow() is in view coordinates, while the model coordinates have been changed by the intervening update. Quoting from the relevant tutorial section:
This distinction does not matter unless your viewed data has been rearranged by sorting, filtering, or user manipulation of columns.
You will need to use the conversion methods described near the end of Sorting and Filtering, which suggests:
When using a sorter, always remember to translate cell coordinates.
When you click on Jtable header to sort it, and click on a row (ex. 3rd row), you will get the value of unsorted JTable's row. To avoid this situation, use this LOC.(ik this is irrelvant to what you're trying to do but for others w/ similar problems)
int row = tblUser.getSelectedRow();
//Without below line, the value you get would be the row before sorting
int correctModel = tblUser.convertRowIndexToModel(row);
//Get username and use it to find its corresponding tuple
String username = (tblUser.getModel().getValueAt(correctModel, 1)).toString();
My table looks like this and Im trying to get the username of the selected row and w/o the 2nd LOC, I'd get the unsorted JTable's row value even after sorting it:
---------------------
| id | username |
---------------------
| | |