Does JTable have a sort event? - java

I have a program which uses a JTable.
I have given it a RowSorter so that when you click on the column headings the table sorts by that column.
I want to capture the user clicking on the column header and output a debug message.
e.g.
System.out.println("You have sorted by first name ascending");
System.out.println("You have sorted by first name descending");
System.out.println("You have sorted by last name ascending");
So I need to respond to the sort event.
I have searched for examples online but I can't find any.

Yes, but it is not part of JTable but RowSorter. You can add a RowSorterListener:
table.getRowSorter().addRowSorterListener(new RowSorterListener() {
#Override
public void sorterChanged(RowSorterEvent e) {
// Sorting changed
}
});

Related

Getting an object from JTable

I want to get information about user from the JTable. Everything is okay, but when I sort the array by name, the objects get read wrong. Example:
Here is everything ok
Above everything is ok. I choose 4 value from the table, shows me 4 items from the Users list. Two books are displayed. But now I sort by 'number of loans', and i choose user with two loans. But the array reads as 'you chose the first value' and shows the first value from the User list.
After sorting
I'd like to receive a specific user after selecting from the board. Thanks.
My code:
tablicaWypozyczen.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
int row = tablicaWypozyczen.rowAtPoint(e.getPoint());
int col = tablicaWypozyczen.columnAtPoint(e.getPoint());
if (row >= 0 && col >= 0) {
JOptionPane.showMessageDialog(null, Dane.uzytkownicyZWypozyczeniami.get(row).toString(), "Informacje o użytkowniku", 1);
System.out.println(tablicaWypozyczen.getSelectedRow());
}
}
}
});
but when I sort the array by name,
Why are you sorting the Array?
Data is stored in the TableModel. The sorting should be done on the table, not on data in some external array. You don't want data in two places, it is too hard to keep the data in sync.
Read the section from the Swing tutorial on Sorting and Filtering for more information.
If you want to get the sorted value from the table you use:
table.getValueAt(table.getSelectedRow(), theColumn);

JComboBox Item Listener - Does not work in if statement

Good day to all,
I have a JComboBox which contains the following items:
"SELECT WHICH ROW / COLUMN / SAMPLE"
"ROW"
"COLUMN"
"SAMPLE"
If the user selected ROW or COLUMN, it would display another JComboBox which would allow users to select the specific Row or Column it wants to display. On the other hand, if the user has selected SAMPLE, it would display a JTextField which has its own purpose on other parts of my code.
My question is, why is it when I check in my actionPerformed function whether the item ["SAMPLE"] has been selected in my JComboBox, it does enter that certain if statement?
if(selection1agraph.getSelectedItem().toString().trim().equals("SAMPLE"))
Here is the segment of my code:
- selection1a is a JComboBox that has the same functionality with selection1agraph, but differs with its contents
- selection1agraph is the JComboBox where the problem occurs
- selection2a is the JComboBox which would be displayed when the user selects either Row or Column
- selection4 is the JTextField which would be displayed when the user selects Sample
- values is a HashSet which allows me to compare multiple variation of Strings
I have used the same else if statement for selection1a and selection1agraph because they have the same functionality execpt that selection1a only contains the following items:
"SELECT WHICH ROW / COLUMN"
"ROW"
"COLUMN"
else if (ie.getSource() == selection1a || ie.getSource() == selection1agraph) {
if (ie.getItem().toString().trim().equals("ROW")) {
.... //other code here
}
else if (ie.getItem().toString().trim().equals("COLUMN")) {
.... //other if and else if statements here
else if (ie.getSource() == selection1a || ie.getSource() == selection1agraph){
selection2a.setEnabled(true);
if(ie.getSource() == selection1agraph){
if(values.contains(selection0.getSelectedItem().toString().trim())){
System.out.println("Entered values.contains(selection0)");
if(selection1agraph.getSelectedItem().toString().trim().equals("SAMPLE")){
System.out.println("Entered selection1agraph.getselectedItem()");
selection2a.setEnabled(false);
selection4.setEnabled(true);
selection4.setVisible(true);
}
}
}
}
}
}
Thank you to those who will be able to help.

Select A row from Jtable based on Jtextfield Input

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.

Preserve selected model row in sorted JTable across model update

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

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