1

JTable stores rows which can be added, deleted, shuffled, dynamically. In my implementation row represent a Download, whose progress can be dynamically updated, by passing value of one of the unique attribute called id. But how do I map id with actual row?

Iterating over the column is not efficient approach. Is there any way to dynamically synchronize Hashmap<ID,Object[]> with JTable, such that given a key I can update corresponding row, and vice versa?

private dftTasks=new DefaultTableModel();
public void addTask(String type, String name, int progress, int sessionID) {
    Object[] rowData={type,name,new Integer(progress),new Integer(sessionID)};      
    dftTasks.addRow(rowData);
}

public void updateProgress(int sessionID, int progress) {
    int i = dftTasks.getRow(sessionID); //<--alternative to this method
    dftTasks.setValueAt(new Integer(progress), i, 2); //2nd column=Progress
}
Nilesh
  • 2,089
  • 3
  • 29
  • 53
  • Try a concurrent hash map to store the values, and as for the array, I believe that there is an atomic array, and use a custom implementation of the TableModel instead of using the DefaultTableModel – MJSG May 31 '15 at 15:51
  • http://stackoverflow.com/questions/2257309/how-to-use-hashmap-with-jtable – Alexei Kaigorodov May 31 '15 at 15:52

2 Answers2

1
  1. Create a class to encapsulate the data (eg type, name, progress, and id).
  2. Store instance of (1) in a List, and if necessary any other data structure for quick access (eg a Map keyed by id). The order of this List is the row order of the table.
  3. Extend AbstractTableModel, and implement the necessary methods to return the values from the List from (1) and (2) based upon the row/column.
  4. When values of the instances from (2) are changed (eg, the progress updated), call fireXXX from within the implementation in (3) (the source of DefaultTableModel is a good example of how this is done)
copeg
  • 8,290
  • 19
  • 28
1

You just answered your own question - use HashMap:

private dftTasks=new DefaultTableModel();
Hashmap<Integer,Object[]> map = new Hashmap<Integer,Object[]>();
public void addTask(String type, String name, int progress, int sessionID) {
        Object[] rowData={type,name,new Integer(progress),new Integer(sessionID)};
        map.put(progress,rowData);      
        dftTasks.addRow(rowData);
    }

    public void updateProgress(int sessionID, int progress) {
        //int i = dftTasks.getRow(sessionID); //<--alternative to this method
        Object[] i = map.get(sessionID);
        dftTasks.setValueAt(new Integer(progress), i, 2); //2nd column=Progress
    }

To do vice versa and listen for changes use TableModelListener to listen for the changes,

Alex
  • 4,457
  • 2
  • 20
  • 59
  • Modern Java has [Autoboxing]( https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html) which does the trick – Alex May 31 '15 at 17:55
  • Autoboxing converts >between the primitive types and their corresponding object wrapper classes Here Object[] is NOT wrapper.. – Nilesh Jun 01 '15 at 03:16
  • Sorry, you are right. I blindly copied OP line of code and didn't pay attention that it was wrong. Now it is fixed. – Alex Jun 01 '15 at 14:08