I create a simple JTable with TableModel, and I hidden the first column.
I set at my JTable also the TableRowSorter
This is the code that I use to create a table
tableModelArticoliVendere = new MyTableModelDescrizioneArticoli();
tableArticoliVendere = new CustomTableArticoliDaVendereBar(tableModelArticoliVendere);
sorter = new TableRowSorter<MyTableModelDescrizioneArticoli>(tableModelArticoliVendere);
tableArticoliVendere.setRowSorter(sorter);
tableArticoliVendere.addMouseListener(new MyMouseAdapterArticoliDaVendere());
tableArticoliVendere.removeColumn(tableArticoliVendere.getColumnModel().getColumn(0));
If the user click on the one row of the table the mouse listenere are called.
This is the method:
public class MyMouseAdapterArticoliDaVendere extends MouseAdapter {
public void mouseClicked(MouseEvent me) {
JTable t = (JTable)me.getSource();
if (me.getClickCount() == 1) {
String codiceArticolo =((JTable)tableArticoliVendere).getModel().getValueAt(t.getSelectedRow(), 0).toString();
inserisciProdotto(codiceArticolo);
}
}
}
The problem is this:
If I see the complete table and I clik on the one of the row table, I read the codiceArticolo right. If I use the row filter, and I try to click on the first row I have an error.
I have the table with 3 row for example:
TABLE
column 0| column 1
------------------
valore1 | 1
valore2 | 2
valore3 | 3
If I use the filter I have this situation:
TABLE
column 0| column 1
------------------
valore2 | 2
valore3 | 3
if I try to click on the first row, the value of codiceArticolo is valore1 and not valore2.
If I not hidden the column 0, I don't have this error.
When you have sorting or filtering enabled in your table, the indexes of table rows and columns stop lining up with indexes of the model rows and columns. You can account for this using convertRowIndexToModel and convertColumnIndexToModel.
For instance, when you use t.getSelectedRow(), you can adjust like this:
int tableRowIndex = t.getSelectedRow();
int modelRowIndex = t.convertRowIndexToModel(tableRowIndex);
It will also help if you indicate in your code when you are using view indexes and when you are using model indexes.
Related
I have a Jtable set up in a tabbed pane that is filled with an id and checkboxes. The table looks something along the lines of this, where . are the checkboxes.
| VAR1 |
ID | ALL | subVar1 | subVar2 |
------------------------------
id1| . | . | . |
Now, I also have a TableListener attached to this table. What I would like to happen is that, whenever a user presses the ALL checkbox, all the checkboxes in that row need to be selected (ie true). This is the table listener code.
#Override
public void tableChanged(TableModelEvent e) {
if(e.getSource() == assignedTableModel) {
for (int i = 0; i < aTable.getRowCount(); i++) {
boolean isAllChecked = (Boolean) aTable.getValueAt(i, 1);
if(isAllChecked) {
assignedTableModel.setValueAt(Boolean.TRUE, i, j);
}
else {
...
}
}
}
}
Clicking the ALL checkbox causing the table to change, assignedTableModel.setValueAt(Boolean.TRUE, i, j); is called, the table is changed again and therefore calls the listener, which calls this function again.
My question, is there another way of updating the checkboxes? Or is there a way to set a base to get out of the recursion?
EDIT The rows are added dynamically. I'm wondering if adding an actionListener to the ALL checkbox as it's being added will be a solution. I'll come back with how it turns out.
EDIT2 I'd forgot to mention that the whole table is generated dynamically. That means I have no way of knowing how many columns and rows will be present, the only columns I know are ID and the ALL col. Most answers already present deal with hard coded implementations.
whenever a user presses the ALL checkbox, all the checkboxes in that row are selected
So why are you looping through all the rows in your code? The event will be generated only for the row you click and you only need to select the check marks for the columns on that row. Get rid of the looping code.
the table is changed again and therefore calls the listener, which calls this function again.
You need an if condition to identify when the check box in the first column is checked:
if (e.getType() == TableModelEvent.UPDATE)
{
int row = e.getFirstRow();
int column = e.getColumn();
if (column == 0)
{
TableModel model = (TableModel)e.getSource();
model.setValueAt(Boolean.true, row, 1);
...
}
}
Now the change of state on the other columns will be ignored.
Based off of #camickr's response, the following piece of code seems to be doing the trick. Thanks.
#Override
public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.UPDATE && e.getSource() == assignedTableModel)
{
int row = e.getFirstRow();
int column = e.getColumn();
if (column == 1)
{
DefaultTableModel model = (DefaultTableModel) e.getSource();
for(int i=2 ; i<model.getColumnCount() ; i++) {
if((boolean) model.getValueAt(row, 1))
model.setValueAt(Boolean.TRUE, row, i);
else
model.setValueAt(Boolean.FALSE, row, i);
}
}
}
}
Anybody please answer my question.
I have an swt table,
for my project purpose i need to know the row number of table cursor positioned.
simple method use on table: table.getItemCount()
//create a Table
Table table = new Table(parent, SWT.BORDER | SWT.FULL_SELECTION|SWT.CHECK);
//TableColumn Object:tblclmnNewColumn_1
TableColumn tblclmnNewColumn_1 = new TableColumn(table, SWT.LEFT);
tblclmnNewColumn_1.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
//click on this column
System.out.println("Row Index:"+table.getSelectionIndex());
System.out.println("Total Row Count:"+table.getItemCount());
}
});
Seems a little inefficient, but this should do the trick.
From the Eclipse Documentation
int indexOf(TableItem item) Searches the receiver's list starting at
the first item (index 0) until an item is found that is equal to the
argument, and returns the index of that item.
TableItem getRow() Returns the row over which the TableCursor is
positioned.
table.indexOf(cursor.getRow())
You may have to add 1 if you don't want to see row zero.
I have a JTable and any single row in it has associated a different tooltip when mouse hover a row. I have created a "filter" for this table; when it is applied it perfectly hides the rows need to be hidden but when I hover the mouse on the filtered rows, looks like the tooltip is referring to the row that occupied the same row position of the new current row.
For example:
Table
ROW 1 -> tooltip 1
ROW 2 -> tooltip 2
Apply Filter to Table:
ROW 2 -> tooltip 1
So ROW 2 is displaying the tooltip 1 instead of 2.
TableRowSorter<TableModel> sorter = (TableRowSorter<TableModel>) table.getRowSorter();
sorter.setRowFilter(RowFilter.regexFilter(text));
My table that extends JTable has:
#Override
public String getToolTipText(MouseEvent e) {
final int rowIndex = rowAtPoint(e.getPoint());
TableModel model = getModel();
// take the value from the first column of the selected row
String tip = (String) getModel().getValueAt(rowIndex, 0));
return tip;
}
So it looks like using the model is not (quite obvious) updated respect to the filter. I tried using TableModel model = getRowSorter().getModel() too but without any luck.
How can I point to a correct "filtered model" to retrieve the correct row position?
UPDATE:
I have replaced the "rowIndex" code like this:
final int rowIndex = convertRowIndexToModel(rowAtPoint(e.getPoint()));
It partially solves the problem, but when some rows are added dynamically to the table with the filter applied and I hover new rows I get the exception (with relative API description):
IndexOutOfBoundsException -> if sorting is enabled and passed an index outside the range of the JTable as determined by the method getRowCount
You need to convert the views row index to the model's row index
Have a look at JTable#convertRowIndexToModel
You should not override that JTable#getToolTipText method. Just set the tooltip-text on the component returned by your renderer. The JTable will pick it up automatically. You can see this in the implementation of the getTooltipText method of the JTable
I have a table where my columns expand dynamically. Initially I set my table model to have 5 columns since basic information has 5 columns. Among the 5 columns column 2 and 3 are buttons (actually they are hyperlinks in a form of a button) which means that I have set column 2 and 3 to have its own renderer and editor.
table.getColumnModel().getColumn(2).setCellRender(new MyCellRender());
table.getColumnModel().getColumn(2).setCellEditor(new MyCellEditor(table));
//more code for column 3 initializatation
My problem is there are times that a row might have more than 5 colums so I check it by adding new columns everytime I need to add more columns in the model. I use
model.addColumn("ColumnName");
to add new columns. The problem is everytime I add new rows that is greater then the initial row my renderers and editors on column 2 and 3 are reset/gone and are rendered as default. What do I need so that column 2 and column 3 remains. BTW Column 2 and 3 are the only columns that are always rendered as buttons.
You can try to override createDefaultColumnsFromModel in JTable and set your special editors/renderers again. As you modify the model the JTable will re-create the columnModel if getAutoCreateColumnsFromModel is true. As you add new column I think you need this to remain true.
public void createDefaultColumnsFromModel() {
super.createDefaultColumnsFromModel();
getColumnModel().getColumn(2).setCellRender(new MyCellRender());
getColumnModel().getColumn(2).setCellEditor(new MyCellEditor(this));
}
To initially create the table you can use:
JTable table = new JTable(model);
table.setAutoCreateColumnsFromModel( false );
table.getColumnModel().getColumn(2).setCellRender(new MyCellRender());
table.getColumnModel().getColumn(2).setCellEditor(new MyCellEditor(table));
The TableColumnModel and TableColumns will be created automatically.
Now, if you want to add another column, because TableColumns are not automatically created from the model you won't lose your custom renderer/editor but now you need to create the TableColumns manually:
String columnName = "Column X";
model.addColumn( columnName );
// AutoCreate is turned off so create table column here
TableColumn column = new TableColumn( table.getColumnCount() );
column.setHeaderValue( columnNamer );
table.addColumn( column );
I have a simple Swing JTable and a TableRowSorter made by me. However, I would exclude the first column from the sorting, as I want to keep it to show row numbers.
I can't see to find anything, except
sorter.setSortable(0, false);
Which makes the column not clickable, but still sortable when another column is clicked...
So quick question will be: how to keep a column from being sorter by a TableRowSorter?
Thank you!
So, with a JTable (ex below) sorting on column A would produce the following. However, you want the data to sort, but not the row numbers, correct?
|row| column A | |row| column A |
+---+-----------+ +---+-----------+
| 1 | blah blah | --> | 1 | blah blah |
| 2 | something | | 3 | more blah |
| 3 | more blah | | 2 | something |
I would approach this with a TableCellRenderer for column 0. The trick is to ignore the value passed and instead use the row parameter.
public class RowRenderer extends JLabel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object color,
boolean isSelected, boolean hasFocus, int row, int column) {
setText(Integer.toString(row));
return this;
}
}
Note: if you are paginating your table (ie the model does not contain all of the rows; for example only rows 100-200) you will need to advise the cell renderer of the amount to add to row to obtain the row number to display.
A JTable is designed around displaying rows of data, not cells of data, so it isn't really possible to prevent an individual column from sorting, as you put it. Instead I would try modifying your TableModel to return the row index for the value for that column:
#Override public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) return rowIndex;
else {
// handle other columns
}
}
If that doesn't work you could also try modifying the table cell renderer to use the table row index instead.
If the row number isn't part of the data, then it should not be stored in the model.
Instead I would use a row header that displays a row number. Something like you would see in Excel. You can use the Row Number Table for this.