I've been over in the beginners forum working on getting a model for dealing with some complex data interactions. I've started putting a set of classes together, but am losing sight of how I'd ever get the data and results in and out of the table. So I thought I would ask for some advice on the swing side of things. The requirement is that the user enters data in the first four or five columns and the program populates the other two or three columns (one column is optional for the user and needs to be populated if they don't enter a value). For any given row, the three columns that need to be computed require first collecting the rows that have the same values in other fields and then using them to calculate a value that goes in every row used in the calculation. So with these columns-
a b c d e f g
to calculate (e), I first find the values of d for all the rows where (a,b,c) are the same as this row. I then calculate a value of e and put it in each of those rows. I also calculate a d' but that is not exposed to the user. I then collect all the values of c,d', and e which have the same values of (a,b) as the current row. I use the values of c, d', and e to calculate values for f and g (can only have one d' and e per c). I then add those values to all the rows I used for the calculation.
Finally, I take the unique sets of (a,b,e,f) and use that to calculate values that go in another table. I was trying to avoid the expense of looping over all the rows and finding the unique sets of (a,b) or (a,b,c) so I put something together that uses nested hashmaps. For any row, I can enter (a,b,c,d) and in the process of adding the data, all the needed values get computed. But I'm having trouble seeing how to map back to table rows and columns.
The basics of the code is shown below. Any advice on the right way to do this would be appreciated.
Just as you have a DataModel, the JTable has its data in a TableModel. This is an interface which has methods like say, 'getValueAt(row, column)'. At runtime, when the table is rendered (drawn), this method will be called by passing the current row number and the current column number. So, you need to write your own implementation of table model.
There is a DefaultTableModel written in the API which uses a Vector to hold the data. There is also a AbstractTableModel written - which you can extend and use your own internal representation and implementation. You can go through thte tutorial to understand table models.
You should look to represent a row as a bean (which will hold a,b,c values) and say a 'calculate' method which when invoked will calculate the 'd,e.f' values. And then in the table model, you can decide which to show and which to hide.
SCJP 1.4, OCMJEA/SCEA 5.0.
posted 8 years ago
Thanks. Maybe I should have been more specific. One thing I did for practice was create a simple table model using an Object array. I created my own table model based on the DefaultTableModel and also created ny own TableModelListener. It was just a test, so I had two rows the user could edit and when one of these cells was changed, I put the sum (if applicable) in a third non-editable column. So I think I understand the basics enough to handle straight-forward cases.
The table I have been asked to produce requires that certain columns (optionally) are filled by pulling data from all rows with the same values in the first two columns as the column being updated. Then once the new value is computed, it gets placed in appropriate cells for all the columns with that (a,b) pair.
Before I can compute the value, I need to compute another value that requires data from all rows where the first three columns are the same as the current row. Again, I need to write the updated data back to all the rows used in the calculation.
Perhaps more problematic, if the cell that is changing is in column A for example, I need to update all the rows that had the old (a,b) value and then update all the rows that have the new (a,b) value. If the value in column c changes, I need to update ol (a,b,c), new (a,b,c) old (a,b) and new (a,b)
Because my data has a hierarchy of (a,b) and then c, I created a hashmap using (a,b) as the key and the value is an object that includes a hashmap on c. When an object is instantiated in this data hierarchy, all the needed intermediate values get updated. So in a 'batch' processing mode this works great. For example, it's easy to extract the value associated with any given (a,b) pair ot (a,b,c) triplet. BUT, these classes don't know anything about the table or what rows the data came from. So implementing a getRow or getColumn is problematic.
I am trying to learn how to approach this problem in an intelligent fashion. There are lots of options I have been considering.
1. Take my data model class which is now independent of a table representation and add lists indicating what row the information came from. I think I might need to duplicate this at several levels, i.e., add to the (a,b) value class a list of rows, add to the (a,b,c) value class a list of rows, add to the (a,b,c,d,e) value class the specific row that this data item came from (duplicate rows are allowed). I think this could get messy when the user changes an existing value of a or deletes a row, but I think I could end up implementing a getRow and getColumn.
2. Bail on having a separate data model. Instead of trying to be clever, just loop through the table whenever a cell is changed and construct the list of rows that need to be updated on the fly. The only thing that I think this would have trouble with, besides rapid retrieval of the computed values, is knowing what the old value of the row was, so I can update those rows. I'm thinking this might mean keeping two sets of books or some simpler hashmap of what rows were used to calculate the values in the previous iteration.
3. Some other major paradigm change like rebuilding the whole data model each time the table data changes. Then I don't have to worry about adding or changing items in the data model and a fairly simple table model can manage the user input, but building the data model is a bit time intensive.
Then when all this is resolved, each time a cell is updated, the request is that a method be run which uses the unique set of (a,b,e,f) and (r,s) from a different table to create or update a graph. The request is the graph updates anytime a value is added or modified in the table.
My confusion there is perhaps deepest. Let's say I take my datamodel and add arrays to track rows and get methods. I can tell the table to use it as my table data model. But, when the cell data changes, I have to get data from other tables and update graphs. The order has to be right or the graphs are wrong. That seems to argue for a control program where I would keep a data model for the (a,b,c) data and a data model for the (r,s) data and the control program would be handed the table objects and the graph objects. Then it could register as a listener to both tables (data could also change in the other table or in the graph panes themselves that would require updates all around). But then, if the data is a control class, I'm not sure what the appropriate way is for that control class to communicate with the table that rows and cells need to change or for the table to let the control program know rows are added or deleted.
The tutorials are helpful, but cover very simple cases and really I am trying to get my head around the right way to approach a situation where a data change triggers a lot of actions that must be run in a specific order and some of these actions result in the data being changed.
You've gotta fight it! Don't give in! Read this tiny ad: