I am using JXTable which is from SwingX components. If I use setSortable(boolean flag) method then it will enable or disable sorting for all columns.
As of my requirement I want to disable sorting for a few columns and enable sorting for other columns.
Can anyone help achieve this functionality?
Thanks for your reply. Can you help me with using setSorterClass(String sorterClassName) to disable sorting for one column? Could you give me any code examplex? It will be very helpful for me.
SwingX supports a per-column sortable property on the level of the TableColumnExt. It's default value is true, to disable it after column creation
table.getColumnExt(myColumnIndex).setSortable(false)
Or at creation time, use a custom ColumnFactory, like
ColumnFactory factory = new ColumnFactory() {
#Override
public void configureTableColumn(TableModel model, TableColumnExt column) {
super.configureTableColumn(model, column);
if (... your condition to disable sortable) {
column.setSortable(false);
}
}
}
table.setColumnFactory(factory);
table.setModel(model);
JXTable will take care of synchronizing the column property to the sorter, provided it is of type SortController (which is the default)
I think, at least according to what I have found on the net you can achieve it by setting
setSorterClass(null) for that column.
As we can read on the cached web site, as swinglabs tutorial page appears to be down, I bet it has something to do with the recent mess on the java.net service.
"JXTables have column sorting turned on by default. You can disable all column sorting using setSortingEnabled(boolean allowSort). You can also disable sorting on a single column by using setSorterClass(String sorterClassName) with a null sorter class name."
Personally, I think there is no point to block user from sorting on a selected table column. Anyway if a user wants to sort a column he/she should be able to do so, in the end I believe it is better to allow a user for more then less, of course when it goes to such details as what he/she can control in his/hers view.
I think you should have a look at TableRowSorter API and see whether JXTable supports it like:
TableModel myModel = createMyTableModel();
JTable table = new JTable(myModel);
table.setRowSorter(new TableRowSorter(myModel));
TableRowSorter has an API method isSortable():
public boolean isSortable(int column)
Returns true if the specified column
is sortable; otherwise, false.
Parameters: column - the column to
check sorting for, in terms of the
underlying model
Returns: true if the
column is sortable
Related
I'm using jComboBox to select a Supplier from table so I have created -1 id row in a table for "none" selected Supplier.
-1 row is also appearing to user where I've fetched all records in
jTable.
I don't want user delete this row may either accidentally or consciously.
So may I have something like this?
I'm using MySQL and Java.
String comName = (String) jSupplrsComboBox.getSelectedItem();
Suppliers suppliers = manager.searchSuppCompny(comName);
if (comName.equals("none")) {
receivings.getSuppliers().setId(-1);
receivings.setSuppliers(suppliers);
}
receivings.setSuppliers(suppliers);
Fetched Suppliers to jComboBox and just manually addd "none" text so it doesn't match in Suppliers table.
I'm not sure what exactly you're trying to achieve, but if you're utilizing a JComboBox, I imagine you're filtering your database by the supplier indicated by the comboBox selection. This also means your comboBox model needs to be populated with entries that exist in your database.
This is a quick way to set Strings to the ComboBox from an Enum, passing entries from the database should work in a similar way, but ensuring duplication does not exist may need to be addressed
jSupplrsComboBox.setModel(new DefaultComboBoxModel<>(SupplierId.values()));
From link Java - Check Boxes in a JComboBox, response by Jonathan Feinberg might be better suited for more than one filter.
As for MYSQL, I'm assuming you have access to make modifications, it may be better if you add an extra field, say isValid, to indicate if said entry is valid or not. In which case you can filter on jSupplrsComboBox.getSelectedItem() with an additional WHERE isValid = 1.
But your question was geared more towards Java than MYSQL, so I won't mention more on that. Check out MySQL Boolean Question and associated links for more on that.
Well I tried myself and where I'm retrieving records I changed code:
DefaultTableModel suppliersModel = (DefaultTableModel) jSuppliersTable.getModel();
for(Suppliers suppliers : manager.allSuppliers()) {
suppliersModel.addRow(new Object[]{suppliers.getId()});
int id = (Integer) suppliersModel.getValueAt(0, 0);
if(id == -1) {
suppliersModel.removeRow(0);
}
That retrieve records after first row which is -1 id in the database table.
Tahnks.
I wanted to ask for a clarification about the use of RowFilter and its effects on performances.
I implemented a filter through the method include(Entry) that for every row simply checks if its correspondent value in the model has a boolean flag set: if so, returns true, else false.
Now, the JTable I have can be pretty big (1000000+ rows), and I wasn't sure if this simple filtering, applied to such a big input set, could be costly.
How does the mapping between filtered rows and underlying data work exactly? I mean, does it store any extra data or it just draws the rows that match the filter "on the fly"??
Thank you very much for the clarifications.
no component in any of programing languages aren't designated to displaying too largiest matrix of data on the screen, then you have two choises
faster way is let's this job for SQL engine, that designated for searching and filtering rows in hugest Database table
slower way is hold these data in HashMap and there apply Comparator, and JTable would be display only result from this Comparator
Expanding on #mKorbel's second point, a TableModel for a very large data set may contain a List<Record>, as suggested here. The list may be sorted using a suitable Comparator and dynamically partitioned using the subList() method. At any one time, the corresponding JTable can only see one such partition, and separate controls will be required to change partitions.
using a jtable -
Can I get the object behind the row
The data displayed in a JTable should be backed by a TableModel, in general a class mapping from a set of business objects to a "table-like" display.
Have a look at the Swing tutorial.
If you tell us more about your usage scenario, one might come up with a good pattern...
As of now, #ChrisJ has the best tip.... YOu can return the POJO in one of the getValueAt columns...
I would like to implement a JTable which will only be edited and updated programatically. I dont want user interaction enabled.
Firstly the input will be from an array of string elements(after filling the array from a String split).
I then want to set the fields with the array data.
How are the column names stored as Final or whatever for the table life?
Do I need to implement a TableModel if I dont want interaction?
You should probably read through the Java documentation for How to Use Tables.
Things you seem interested in:
isCellEditable() - Have it return false means the user can not edit any cells.
getColumnName() - Look up the name in an array or list of strings.
Regarding editability: use JXTable - it supports layered programatic configuration control. Specifically,
supports per-column and per-table narrowing (that is, to read-only)
respects the cell editable property always (that is table.setValueAt does nothing if the cell is not editable)
Yes, the model will be useful but not necessary (also just a DefaultTableModel).
Actually you could just fill the JTable with static data using the right constructor:
public JTable(Object[][] rowData, Object[] columnNames)
but you won't have any control over the data inside the table.
The model is not used just to provide interaction with editing capabilities but to provide a data source for the table either to read either to write, that's why it's always good to have one.
In my application I have a JTable and a List.
The List:
The list is populated using a JPA query. The user can re-execute the query by changing attributes in the GUI. Let's assume the query has a named parameter "year" and the user can change this. Then the following happens (simplified by leaving out exception handling):
myList.clear()
mylist.addAll( myQuery.setParameter("year", 2010) )
As the list changes, the binding fires the required handlers and the table now reflects the new dataset.
The JTable:
The contents of the JTable come from a BeansBinding (more precisely a JTableBinding). The binding source is the aforementioned list.
The query is only executed for intensive tasks. Like applying a rough filter on a huge dataset. The earlier example with the year is a good example. This will always return a manageable chunk of data to the client. Now, to have a more responsive user experience, more fine-grained filters happen in the JTable itself. This avoids unnecessary round-trips to the database.
Next, assume the following scenario: A user selects a row in the table and hit's the delete button. If the table has not been filtered the required code is straightforward (again, no error-checking, concurrency locking, and exception handlers for code simplicity):
MyObject = myList.get( myTable.getSelectedRow() );
myEntityManager.getTransaction().begin()
myEntityManager.remove( myObject )
myEntityManager.getTransaction().commit()
However: If the table is filtered on the client side, the table won't reflect the data inside the List. So getSelectedRow() will not return an index which will map to the same entry in the List (I have not tested this, but I beleive I am correct with this assumption?)
So... My question:
How best to solve this?
A possible solution?
I've solved the problem at hand with the following:
I created a new Bean called selectedTableElement which contains a member holding the element which is currently selected in the table.
Next, I created a new binding (source: my table, target: my "selectedElement" bean) using
binding = Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, myTable, ELProperty.create("${selectedElement}"), selectedTableElement, BeanProperty.create("selectedElement"), "selectedElementBinding");
This solution effectively solves the problem by keeping track of the selected element of the table using Beans Binding.
But is this really necessary? It feels clunky to me. A whole new class only the encapsulate the selected element? Is there no other, more direct way of retrieving the "${selectedElement}" property of the JTable?
I'll try to answer to both your questions.
Regarding the first question (the filtered selected index vs the real list index):
I assume that you bound the table using BeansBinding, via createJTableBinding. So, the client-side filtering might be applied through the use of swing TableRowSorter and RowFilter. Am I right ? if so, you could use the method
int row = myTable.convertRowIndexToModel(myTable.getSelectedRow());
to convert the selected row in the filtered view to the actual selected row in the model.
For the second question (bean to keep the selected item of table)
You could also create a binding using this as the source/target object, and create a property selectedElement in the class containing the table. Thus, you won't need another class. The code will be : createAutoBinding(UpdateStrategy.READ_WRITE, myTable,
ELProperty.create("${selectedElement}"), this, BeanProperty.create("selectedElement"), "selectedElementBinding");
(note also that READ_WRITE binding is not really used, as beans binding does not support changing the selected element from the bound property)