Modify cell editor for different rows in a JTable - java

I have a JTable with the following columns:
rowNumber | Element | Quantity
And a JButton that adds rows every time it's clicked. The column Element has a custom JComboBox cell editor that gets filled with elements from a database. However i need to do the following:
Suppose i have these elements in the JComboBox of the first row in my table:
Element1
Element2
Element3
I select Element2 from the JComboBox in the first row and then I proceed to add another row.
This new row must not show Element2 any more in its JComboBox. And the previous (first) row must not show the Element selected in the second row and so on.

I think it may help to know the expected cardinality of the Set<Element>. Accordingly, #mKorbel raises the important question of scalability, citing this related discussion. In that case, the question proposes a List<DefaultCellEditor>, when a much simpler renderer will do.
Here, a CellEditor can manage a List<DefaultComboBoxModel<Element>>, selecting the correct combo model for the row currently being edited and invoking setModel() on the editor component. As each new table row is added, the editor would add a new element to the List and adjust existing elements as required. I would expect the complexity to grow as O(n2), where n is the cardinality of the Set.

Create a custom CustomCellEditor like this.
final JComboBox<String> comboBox = new JComboBox<String>();
table.getColumnModel().getColumn(1).setCellEditor(new CustomCellEditor(comboBox){
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) comboBox.getModel();
model.removeAllElements();
{//Add what you need according the row.
model.addElement("X");
model.addElement("Y");
model.addElement("Z");
}
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
});

Related

java swing - deselect a selected row in jtable

I have an instance of JTable in my java swing application. I want to deselect a selected row from this table. From This answer, JTable has provided clearSelection() method that deselect all selected rows in the table. But I want to deselect one row. How can I do this?
Have you tried:
ListSelectionModel.removeSelectionInterval(int index0, int index1)?
See this it toggles the selection of a row in jtable.
You can do this like that:
JTable table = new JTable(); // your table instance
TableModel dataModel = new DefaultTableModel(); // table model
DefaultListSelectionModel selectionModel = new DefaultListSelectionModel(); //table selection model
table.setModel(dataModel);
table.setSelectionModel(selectionModel);
int desiredRow = 0; // row which you want to deselect
selectionModel.removeSelectionInterval(desiredRow, desiredRow); // Removing selection for desired row

Updating data in JTable when object changes

Let's say I have this JTable:
private JScrollPane scrollPane1;
private JTable table;
private DefaultTableModel model;
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Item");
model.addColumn("ID");
model.addColumn("Price");
model.addColumn("Category");
this.scrollPane1 = new JScrollPane();
this.scrollPane1.setBounds(33, 518, 604, 300);
this.contentPane.add(this.scrollPane1);
table = new JTable(model);
this.scrollPane1.setViewportView(table);
I have an Item class, so when I create a new instance of Item, I add the items info to the JTable:
Item item = new Item("Shovel", 1, 123, "Tools");
model.addRow(new Object[]{item.getItem(), item.getID(), item.getPrice(), item.getCategory()});
So far so good.
But if I update the Item, for example change the price from 5 to 10, it is not updated in the JTable. So if I for example do:
item.setPrice(10);
It doesnt update in the JTable. I've tried calling model.fireTableDataChanged(); and table.repaint(); but none of them works. It seems like the value in the cell is not associated with the objects value? How would I do this? (First time working with JTables).
Any suggestions? Don't be bothered by the lack of methods etc., I just put this together quickly for this post.
EDIT: My Item objects are stored in a HashMap.
Actually, you are not modifying any cell in the table, the item object is not associated with your table directly, your making a now values in the table by using the same values from the item object.
what you has to do is to update the cell itself then by overriding the below method from AbstractTableModel class:
#Override
public void setValueAt(Object value, int row, int col) { //
Then call
model.fireTableDataChanged();

JavaFX: Get the selected row cell's text

I need your help.
I am developing JavaFX project that deals with table view and forms.
My Problem is I can't get the text of the selected row in the table view.
I want to get the row cell's text using the row index or the selected row one.
Here is my code:
myTableView.getSelectionModel().selectedItemProperty().addListener( new ChangeListener() {
#Override
public void changed(ObservableValue ov, Object t, Object t1) {
TableView.TableViewSelectionModel selectionModel = myTableView.getSelectionModel();
ObservableList selectedCells = selectionModel.getSelectedCells();
TablePosition tablePosition = (TablePosition) selectedCells.get(0);
int rowIndex = tablePosition.getRow(); // yields the row that the currently selected cell is in
// I Want to get the cell's text in the row using the row_index or the selected row one
}
});
Any solution is appreciated. Thank you!
If you only care about which row is selected, assuming you have a TableView<SomeObject>, you can simply use:
List<SomeObject> selected = selectionModel.getSelectedItems();
or if your table only allows single row selection:
SomeObject selected = selectionModel.getSelectedItem();

JTable's and DefaultTableModel's row indexes lose their synchronization after I sort JTable

JAVA
NETBEANS
// resultsTable, myModel
JTable resultsTable;
DefaultTableModel myModel; //javax.swing.table.DefaultTableModel
myModel = (DefaultTableModel) resultsTable.getModel();
// event of clicking on item of table
String value = (String) myModel.getValueAt(resultsTable.getSelectedRow(), columnIndex)
I use JTable and DefaultTableModel to view a table of various info
and I want to get a value of a certain column of the selected index of the table.
The code I wrote above works fine except when:
I use the sort of the GUI (click on the field name I want to sort on the table)
The table is properly sorted but after that when I select a row, it gets
the value of the row that was there before the sort.
This means that after sorting (using the JTable's GUI)
the 'myModel' and 'resultsTable' objects have different row indexes.
How do I synchronize those two?
You need to use the 'convertXXX' methods on the JTable see the JavaDoc
int row = resultsTable.getSelectedRow();
if (row != -1) {
row = table.convertRowIndexToModel(row);
String value = (String) myModel.getValueAt(row, columnIndex)
A problem with using the JTable.getValueAt() is to get the column you want. When the columns are moved around in the GUI the indexes "change" to match the view. By using the AbstractTableModel.getValueAt() and the JTable.convertXXX() (as outlined by Guillaume) it's just a matter of using the column indexes for the model when retrieving data.
Except from the solution Guillaume gave (Thanks)
I did this:
// resultsTable, myModel
JTable resultsTable;
DefaultTableModel myModel; //javax.swing.table.DefaultTableModel
myModel = (DefaultTableModel) resultsTable.getModel();
// event of clicking on item of table
String value = (String) **resultsTable**.getValueAt(resultsTable.getSelectedRow(), columnIndex)
I used the resultsTable Object instead of the myModel Object to get the value.

How to make a columns in JTable Invisible for Swing Java

I have designed one GUI in which I have used one JTable from which I have to make 2 columns invisible . How should I do that ?
Remove the TableColumn from the TableColumnModel.
TableColumnModel tcm = table.getColumnModel();
tcm.removeColumn( tcm.getColumn(...) );
If you need access to the data then you use table.getModel().getValueAt(...).
For a more complex solution that allows the user to hide/show columns as they wish check out the Table Column Manager.
First remove the column from the view
table.removeColumn(table.getColumnModel().getColumn(4));
Then retrieve the data from the model.
table.getModel().getValueAt(table.getSelectedRow(),4);
One thing to note is that when retrieving the data, it must be retrieve from model not from the table.
I tried 2 possible solutions that both work, but got some issue with the 1st solution.
table.removeColumn(table.getColumnModel().getColumn(4));
or
table.getColumnModel().getColumn(4).setMinWidth(0);
table.getColumnModel().getColumn(4).setMaxWidth(0);
table.getColumnModel().getColumn(4).setWidth(0);
In my recent case, I preferred the 2nd solution because I added a TableRowSorter.
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
When using table.removeColumn(table.getColumnModel().getColumn(4)), it will physically remove the column from the view/table so you cannot use table.getValueAt(row, 4) - it returns ArrayIndexOutOfBounds. The only way to get the value of the removed column is by calling table.getModel().getValueAt(table.getSelectedRow(),4). Since TableRowSorter sorts only what's on the table but not the data in the DefaultTableModel object, the problem is when you get the value after sorting the records - it will retrieve the data from DefaultModelObject, which is not sorted.
So I used the 2nd solution then used table.getValueAt(table.getSelectedRow(),4);
The only issue I see with the 2nd approach was mentioned by #camickr: "When you set the width to 0, try tabbing, when you hit the hidden column focus disappears until you tab again. This will confuse users."
i had the same problem and because of i am using TableColumnModel removColumn(); does'not help me so i used this
table.getColumnModel().getColumn(0).setWidth(0);
table.getColumnModel().getColumn(0).setMinWidth(0);
table.getColumnModel().getColumn(0).setMaxWidth(0);
and worked fine for me it hide a column 0 and i still able to get value from it
Set the min, max and "normal" width to 0:
jTable.getColumn("ABC").setMinWidth(0); // Must be set before maxWidth!!
jTable.getColumn("ABC").setMaxWidth(0);
jTable.getColumn("ABC").setWidth(0);
Note: Since you can't set a maxWidth < minWidth, you need to change minWidth, first (javadoc). Same is true for width.
The second approach is to extend TableColumnModel and override all the methods to create the illusion (for the JTable) that your model doesn't have those two columns.
So when you hide a column, you must return one less when the table asks for the number of columns and when it asks for the column X, you may have to add +1 to the column index (depending on whether it is to the left or right of the hidden column), etc.
Let your new table model forward all method calls (with the corrected indexes, etc) to the actual column model and use the new table model in the JTable.
If you remove the column from the JTable the column is still present in the TableModel.
For example to remove the first ID column:
TableColumnModel tcm = table.getColumnModel();
tcm.removeColumn(tcm.getColumn(0));
If you want to access the value of the removed column, you have to access it through the getValueAt function of the TableModel, not the JTable. But you have to convert to rowIndex back to rowIndex in the model.
For example if you want to access the first column of the selected row:
int modelRow = table.convertRowIndexToModel(table.getSelectedRow());
int value = (Integer)table.getModel().getValueAt(modelRow,0);
I have tried them all: they don't help. The BEST way ever is to make a new table model without the column you want to delete. This is how you do it:
table = (DefaultTableModel) <table name>.getModel();
DefaultTableModel table1 = new DefaultTableModel();
Vector v = table.getDataVector();
Vector v1 = newvector(v,<column index you want to delete>);
Vector newvector(Vector v,int j){
Vector v1= new Vector();
try{
Vector v2;
Object[] o = v.toArray();
int i =0;
while(i<o.length){
v2 = (Vector) o[i];
v2.remove(j);
v1.add(v2);
i++;
}
}
catch(Exception e){
JOptionPane.showMessageDialog(null,"Error in newvector \n"+e);
}
return v1;
}
Vector getColumnIdentifiers(int i) {
Vector columnIdentifiers = new Vector();
int j=0;
while(j<i){
columnIdentifiers.add(("c"+(j+1)));
j++;
}
return columnIdentifiers;
}
table1.setDataVector(v1,getColumnIdentifiers((<column count>-1)));
<table name>.setModel(table1);
You could create a subclass of the model, and override TableModel.getColumnCount as follows:
int getColumnCount() {
return super.getColumnCount()-2;
}
The last two columns would then not be displayed in the JTable.

Categories