relationship with ArrayList and jTableModel - java

Hej.
There is a collection with data.
static ArrayList<MyBeans> all = new ArrayList<MyBeans>();
There is a jTableModel too which invoke this table on jFrame.
TableModel model = new Table(all);
JTable table = new JTable(model);
For example, at some moment ArrayList<MyBeans> all was changed. What should do for change this table too?

If your all ArrayList<MyBeans> (which by the way should not be static) is the nucleus of a TableModel, then your problem is that you're trying to make changes directly to the ArrayList which you should never do. Instead you should make changes only by calling public methods in your TableModel, and these methods should fire the appropriate AbstractTableModel notification method that will notify any registered listeners (here, the displayed JTable itself) of any changes to its model.

Related

Make custom JTableModel to listen to changes in ArrayList

I got a list of Customers. Each Customer has a List of Accounts and each Account got a List of Transaction.
Recently I have been implementing import/export functionality to my program using ObjectOutputStream/ObjectInputStream. This works and it saves everything and loads correctly.
My issue is that the JTable does not update automatically once the ArrayList has been changed (I have created a custom JTableModel which currently only sets each cell to be non-editable. Is there any listener that fits my needs? My CustomJTableModel extends DefaultTableModel.
I got the trigger to load/save in a custom MainMenu class that contains a JMenuBar and it does not directly know about the TableModel or the JTable (otherwise i could do a "cheap" way and just add it again).
There are methods such as fireTableDataChanged but that only listens to the JTable itself.
Not sure if I need to post any code, thought it was maybe a simple issue and that there is a suiting Listener out there.
My recommendation for your problem would be to implement (Java observer interface ) in your JTable Class and implement (Java observable interface) in your class that exploits and modifies the ArrayList. This way, every time a change occurs to your the arrayList, update method will be invoked and JTable will be updated in consequence.
Here is a tutorial that details on my above explanation
public class JTable implements Observer
{
// this is the method that will be invoked everytime a change has occured.
public void update(Observable obs, Object obj)
{
// To implements as required
}
}
public class Store implements Observable
{
ArrayList<Customers> listOfCustomers;
public void setValue(Customer n)
{
this.listOfCustomers.Add(n);
setChanged();
notifyObservers(); // this will notify your JTable
}
}
This is just a start of how to implement the system.
My issue is that the JTable does not update automatically once the ArrayList has been changed
Well you should not be making changes to the ArrayList.
The ArrayList should be used as the data structure for your TableModel. Then if you want to make changes to the ArrayList (ie adding/removing rows) then this should be done via the TableModel.
See Row Table Model for a step-by-step example on creating a custom model using this approach.
Now, on the other hand, if your problem is that a property of the Object that is stored in the ArrayList changes, then yes, you need to use the Observer pattern.

Which editing and removing row method is better for JTable?

I wanna ask that which method to edit a JTable is better than the other?
use setValueAt() function.
Make a new model of JTable and feed its object to JTable.
And also, how to remove a Row from JTable without using method 2 described above?
You would use the setValueAt method when you're changing one value at a time.
You would make a new TableModel when you're changing 25% or more of the rows at one time.
If you use a DefaultTableModel as your TableModel, you can use the addRow or setValueAt methods to add a row and change a row value. You can use the removeRow method to remove a row.
Since the TableModel is associated with the JTable, any changes to the TableModel are reflected in the JTable. Any changes to the JTable by the user are reflected in the TableModel.

Swing MVC - Data in Model

I'm starting to learn how implement MVC pattern in swing. I have a confusion when in comes to the data in model.
In the application that I'm doing, I have several JTextFields. The data set in the fields come from JTable. I have a ListSelectionListener in my controller added to that jtable (in the view) so that when selection has changed, the data from the selected row will be reflected to the respective textfields
public void transferTableDataToFields(){
if(tblProduct.getSelectedRows().length != 0){
int selRow = tblProduct.getSelectedRow();
txtID.setText(tblProduct.getValueAt(selRow, 0).toString());
txtName.setText(tblProduct.getValueAt(selRow, 1).toString());
txtDescIn.setText(tblProduct.getValueAt(selRow, 2).toString());
txtSupplier.setText(tblProduct.getValueAt(selRow, 4).toString());
txtPrice.setText(tblProduct.getValueAt(selRow, 5).toString());
}
}
My question is, am I doing it the right way? Should I define fields in the model that corresponds to the textfields in my view, then change my code to controller setting the model's fields to values from view's jtable then let the model fire a property change notification to its listener, then let the listener call the update method in the view based on the property change event?
My problem with this approach is that, the view should have a method that will return the row selected from the jtable which I find a bit ugly.
EDIT
#trashgod this is what I'm saying.
Inside my TableModel implementation, is it better to populate the data here?
public MyTableModel extends AbstractTableModel{
List<Row> data;
Row header;
public MyTableModel(){
initializeData();
}
public void initializeData{
//query database here then put it in the list
}
//other methods to implement e.g. getvalueAt(int x, inty){data.get(x).get(y);}
}
Is it better if I make it like this? because currently I stored and populate the data of my table in my main model (also containing fields with corresponding textfields in the SelectedRow view) then I pass the data in my JTable's model.
In this case, the current selection is a property of the view, an instance of JTable, not the model, an implementation of TableModel.
If you choose to supersede editing in the JTable itself, a ListSelectionListener is the correct way to update your (anonymous) dependent view, e.g. SelectedRow. Your controller should have little to do except add SelectedRow as a listener to your JTable. As SelectedRow contains (presumably) editable fields, you are responsible for several things:
Propagate any changes back to the original table's TableModel, typically via setValueAt().
Convert between view and model coordinates, mentioned here.
Preclude (or synchronize via the ListSelectionListener) editing in the source JTable.
Addendum: Inside my TableModel implementation, is it better to populate the data here?
The answer depends on the application. Your TableModel implementation should expose a public API that provides as much (or as little) as required to support the application's requirements for concurrency and latency. For reference, DefaultTableModel is a general purpose example, although you'll want to use something more recent than Vector internally.

Java Swing - inform GUI about changes to the model

I have a column in JTable that binds to the underlying boolean property on a list of business objects. I also have a combobox, which should select which items should be selected. I basically added the following code as a handler to the combobox:
macroCombo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JComboBox comboBox = (JComboBox) e.getSource();
Predicate filter = (Predicate) comboBox.getSelectedItem();
for(SelectableKey key : tableEntries){
key.setSelected(filter.evaluate(key));
}
}
});
I also have a few other controls I want to change based on the value. At the moment, only a few cells in the table change their state to be selected/deselected. Only when I click on the row, or select multiple rows, the UI updates itself. Is there a call from the handler I need to make to tell GUI to redraw itself? ALos, if I modify other controls than JTable, how would I tell them to change their state?
Thanks
When you update a value in your TableModel, the model should fire a corresponding TableModelEvent (type: UPDATE).
If your TableModel for example extends from AbstractTableModel, you can call the fireTableRowsUpdated method after you have made the changes.
Another approach is a TableModel which knows when it gets updated (for example by adding listeners to the objects it contains). This allows other code to simply update the objects contained in the TableModel, without having knowledge of the TableModel. The TableModel itself will then fire the event when it detects changes made to the objects it contains.
I prefer the second approach, as this avoids that I have to pass that TableModel around to all my other classes.
Consult the table tutorial for more information.

Changing a JComboBox model unsing a ListModel. Does it have hidden consecuences?

I use both JList and JComboBox in different places. The content of both change dynamically.
Once a comboBox is created you cant just say comboBox.setModel(String[]), you have to create a new model and then set it to the comboBox.
Same happens with the JList.
Rather than creating my own Jlist and ComboBox just to add a new method called .setNewModel(String[]) i created a static method in my "utility" class that receives a String[] and returns a ListModel.
So i can do this:
someComboBox.setModel((ComboBoxModel)UtilityClass.convetToListModel(aStringArray));
I use the same for the JList.
someList.setModel(UtilityClass.convetToListModel(anotherStringArray));
my question is:
Could the casting of the listModel as a ComboBoxModel have some unexpected consequences?
If so, is there anyway to change the entire content of a comboBox without having to transform the ArrayString into a Model?
here is the code of the method:
public static ListModel convertToListModel(String[] nList)
{
return (new JComboBox(nList).getModel());
}
The program compiles and runs fine, but casting always generates doubts in me, specially complex objects.
Yes i know i can extend JComboBox and JList to add a method that does the job but its a lot of extra work. Why the ComboBox and Jlist don't have a update or modify Model than accept a simple array of Strings?
How is
someComboBox.setModel((ComboBoxModel)UtilityClass.convetToListModel(aStringArray));
in any way easier to write/simpler/whatever than
someComboBox.setModel(new DefaultComboBoxModel(aStringArray))
all you added is white noise in the form of the Utility method. Plus
the implementation of that method is simply ... crazy: you create a JComboBox just for the sake of accessing the model that's internally created by that combo ...
you have to exploit implementation to type-cast for usage in a real combo ...
Don't do such wasteful/unnecessary stuff, don't even think of going any detours when there's a simple straightforward manner to reach the same goal
If the contents of the list/combobox need to change dynamically, then you should manage the model itself directly. You shouldn't create a new model each time and replace the old one. The whole point of having a model is that you can update the data it contains.
Simply create your own DefaultListModel or DefaultComboBoxModel and pass it into the JList/JComboBox. Then use the model's add/remove methods as needed to update the contents when it changes.
private DefaultComboBoxModel model = new DefaultComboBoxModel();
private JComboBox combo = new JComboBox(model);
...
model.addElement(somethingForMyList);
...
model.removeAllElements();
...
model.removeElement(elementToRemove);
Usually I would prefer to implement a new class that is inherited from DefaultComboBoxModel (therefore it's also a ListModel as well as a ComboBoxModel). This new class would be enriched with methods to update the model as any possible situation demands. In the update methods you would call fireContentsChanged to tell the enclosing component that the contents have changed and the component should redraw everything.
Hope it helps.

Categories

Resources