user1761818
user1761818

Reputation: 375

How I can use arraylist to store my data in predefined default table model for JTable

I want to add data to my own JTable model in runtime. I have the table and add button on my interface. As I understand I cant do it with two dimensional array and want to use Arraylist in my custom made table model but I dont know how to make the constructor if I use such type of data.

static String[] columnNames = {"A", "B", "C"};
static Object data[][] = new Object[15][3];

public MyTableModel() {
   super(data, columnNames);
}

this is the constructor for data as two dimansional array but I want to use:

ArrayList<Object[]> data = new ArrayList<Object[]>();

How to make it

Upvotes: 2

Views: 7022

Answers (3)

Jay
Jay

Reputation: 27492

The most straightforward way to create your own table model is to inherit from AbstractTableModel. Then override, at a minimum, getRowCount, getColumnCount, and getValueAt.

You can then either create the table using "new JTable(mymodel)", where "mymodel" is an instance of the model you have created, or you could create it with just "new JTable", and then later do setModel to attach your model to the JTable.

For example -- and while I've done this a bazillion times, I'm writing this off the top of my head so no warranties expressed or implied, odds are there's a syntax error or two in there somewhere:

class ArrayListModel extends AbstractTableModel
{
  ArrayList<Object[]> list;

  public ArrayListModel(ArrayList<Object[]> list)
  {
    this.list=list;
  }
  public int getRowCount()
  {
    return list.size();
  }
  public int getColumnCount()
  {
    if (list.size()==0)
    {
      return 0;
    }
    else
    {
      return list.get(0).length;
    }
  }
  public Object getValueat(int row, int column)
  {
    return list.get(row)[column];
  }
}

... somewhere else ...
ArrayListModel mymodel=new ArrayListModel(somedata);
JTable mytable=new JTable(mymodel);
... etc ...

Side note: When I was first learning Java, I thought that the "normal" way to create a JTable was to use the default model, create a vector of vectors or a 2-D array and then populate. I thought creating your own model would be something you did in rare, odd cases. But I've since figured out that the default model is only the best way in rare, simple cases. Now I almost always create my own model: it's usually easier to code and easier to understand. Typically I have an ArrayList of some class that I've created with specific fields, and then in my model class I have something like:

 public Object getValueAt(int row, int col)
 {
   Whatever w=list.get(row);
   if (col==0) return w.foo;
   else if (col==1) return w.bar;
   else if (col==2) return w.plugh;
   else throw SomeException();
 }

Or use a case statement. Same idea.

Upvotes: 0

Guillaume Polet
Guillaume Polet

Reputation: 47617

One way to do it, is to use AbstractTableModel. Here is an example:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;

public class TestTable {

    public static class MyModel extends AbstractTableModel {

        private List<Object[]> data;
        private List<String> columnNames;

        public MyModel(List<String> columnNames, List<Object[]> data) {
            super();
            this.columnNames = columnNames;
            this.data = data;
        }

        @Override
        public int getRowCount() {
            return data.size();
        }

        @Override
        public int getColumnCount() {
            return columnNames.size();
        }

        @Override
        public String getColumnName(int column) {
            return columnNames.get(column);
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return data.get(rowIndex)[columnIndex];
        }

    }

    protected void initUI() {
        JFrame frame = new JFrame(TestTable.class.getSimpleName());
        List<String> columns = Arrays.asList("Name", "Age");
        List<Object[]> data = new ArrayList<Object[]>();
        for (int i = 0; i < 50; i++) {
            Object[] value = new Object[2];
            value[0] = "Name-" + i;
            value[1] = 12 + i;
            data.add(value);
        }
        JTable table = new JTable(new MyModel(columns, data));
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestTable().initUI();
            }
        });
    }
}

If you need to to modify your data List<Object[]>, don't forget to fire appropriate Table Events. AbstractTableModel contains them all already.

Upvotes: 4

CodeBlind
CodeBlind

Reputation: 4569

It's a bit hard to tell what you're doing as you haven't included the full source code of your table model, so I'm going to make a few assumptions here.

You're probably either extending AbstractTableModel or DefaultTableModel. In either case, you shouldn't have to add your data to the model via the constructor. Instead, you will want to override the following methods in your TableModel extension:

getRowCount()

getColumnCount()

getValueAt(int row, int column)

Make it so that each of these methods indexes into your ArrayList<Object[]> data object - e.g., getValueAt(row,column) should return something like data.get(row)[column]. Then add your TableModel to a JTable and you should be good to go, as far as displaying the custom data goes.

Now... when your data changes (either you changed the value of a cell in the table or you added/removed rows), you just call fireTableDataChanged() on your TableModel (assuming it has extended AbstractTableModel or one of its subclasses). This will force the UI to update with the changes you made to the underlying data.

Upvotes: 0

Related Questions