Suppose, I would like to implement data validation in JavaFX TableView.
Once user have changed data in the row, I would like to check it when user is trying to change current row number. Once data is correct, I would like to allow row change, once data is incorrect, I want to disallow this.
How to implement this?
Currently, I am trying to add a listener
getSelectionModel().selectedIndexProperty().addListener(indexFromTableToModel);
but any operations inside it causes bad table view behavior. Using
Platform.runLater
makes situation better, but still imperfect.
Is there a convenient place, to perform row data validation and perform different operation depending on it?
You can write your own selection model that can be locked (if current value is invalid). In that case the model won't change the internal selected index.
Related
When changing the number of columns and rows of natTable
After clearing the column list of DataProvider, create a new column item and change the column item list of columnPropertyAccessor.
Then, put the new data model into the filter list and refresh it.
When the 7-column nattable is sorted (ascending or descending) and clicked, it is changed to a different data model (4 columns) as above, but if it is sorted, "CurrentModificationException" and "IndezxOutOfBoundException" occur.
If you exchange data models without sorting, there is no problem.
I don't know which part is causing it.
Is my way of replacing the filter list wrong when changing the data model?
If anyone has encountered a similar error and has solved it, please help.
Well you don't show how you are doing things, so I can't tell any details. But to answer your question, yes I think you are doing things wrong.
In short, if you have a state applied according to a column like sorting or filtering and you change the underlying data structure, things will break as the states does match the structure anymore. Not sure why you think this should work automatically.
If you change the underlying data structure you need to clear structure based states in advance.
There is an example in the NatTable examples application that shows how to change the data provider dynamically. Not sure if the example covers the clearing of states or if this is handled automatically when you are doing things correctly.
Currently im doing on a project on ordering system. Let me explain the flow of the system. In ordering class, i have 2 jtable. One of the jtables shows the list of food retrieve from the database. I just have to click on one of the food and press"add", the selected food will transfer to another jtable . After i press"proceed" i will be led to a jtable, to the next jpanel, which consists of the food i have selected. However" i allow one cell to be editable,"quantity" is there any way on how to retrieve the data input by the user and store to database?
Depending on the implementation of the TableModel, you could get the data for an individual row. This would, generally, be the preferred solution, as the data for the row would be encapsulated within a POJO which maintains all the data that you need in a single place that easily manageable.
If you've just dumped a bunch of unassociated properties into the table, you will need to use something like JTable#getValueAt or TableModel#getValueAt
See How to Use Tables for more details
I am working with the com.sencha.gxt(3.0) grid widget. I am trying to write a Java function that searches for a string in a row(across all columns) and only display the rows that contain this string. Is there a built in, or easy method in which I can do this?
Thanks
No.
(I'm pretty sure you didn't actually mean to write a "yes or no" question...)
In short, it would be silly for GXT to assume that all data in your grid is a string or string-like or only makes sense to compare in string-y ways. Plus, you might have all your data locally so it makes sense to do a simple filter on the client, or you might really be saying 'please search all ten million rows, on the server/db, and only send back the ones that match to render on the client.
Client-side filtering
The Store (probably a ListStore for a grid, or a TreeStore for the tree grid, but your question doesn't specify) has a built-in method for local filtering - you give it a function that takes an item (and some other possibly-relevant data), and returns true/false indicating whether or not the item should be hidden from the user. More than one filter can be applied, and if any filter says the item is hidden, then it is gone. In other words, this can be thought of as a sql where clause, where all statements are joined with and - if you want or, you can implement a filter that checks if any single filter wants the item visible.
This filtering mechanism operates over the entire row item, the T in Store<T>. It doesn't know what a column is, since you could be using the store in any number of ways - items in a combobox, points on a chart, etc. It lets you build your own tools to perform the filtering. If your data is generalized in a way that makes it easy to know what all possible columns are, then you could easily write a loop over those columns that checks if any one of them contains the string, in which case return false so that the item is visible. Or, since you already built the ColumnModel full of ColumnConfigs, each of which has a ValueProvider and you know that it makes sense to compare each value with .toString().contains(queryText), you could iterate over the columns that way.
Server-side filtering
In this case, we have very little control on the client of what is happening, since you are very likely off-loading that work to your backend database. We still know the list of columns in the column model, but we either send a query for cells matching that text, or send a single query for the entire row. Either way, we modify the paging load config object that is being used, and send a new query for the data we want, and the actual work of doing the filtering is the server's job. It sounds like from your question that this is not what you want, but without a lot more detail, its hard to say for sure.
You can achieve this through filtering.
Initially, the grid takes an argument as store and modification to the store will be directly reflected on the User Interface.
To enable filtering:
store.setEnableFilters(true);
To filter the grid, use the following commands:
store.addFilter(new StoreFilter<M>()
{
#Override
public boolean select(...,...,...)
{
//return true if you want to display the row, else false
}
}
My question in its simplest form: Is it possible to determine the subset of items (or the indices of the corresponding items) currently being displayed in a JavaFX TableView?
The reason I'm asking is that I want to implement lazy loading. Therefore, I subclass ObservableList and implement the code that fetches new items from the database in the overriden E get(int index) (using prefetch/cache). However, the entity objects might be changed by the user and are therefore observed by the database backend. That's why I'd like to detach them as soon as they are not displayed any more.
Many thanks in advance for any suggestions.
You can use VirtualFlow to get the indizes of the first and the last visible cell: Scroll TableView via a Button
However, as I understood it, this is more a hack then a real part of the API. Also you might run into trouble if you have more tables around, it will be triggered each time a table changes.
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)