Search code examples
arraylistjtablerowadditionabstracttablemodel

Duplicate Row in JTable using AbstractTableModel and ArrayList


I am using a JTable and extending an AbstractTableModel to do so. My data container is an ArrayList of "Entries", a data structure I defined to store a group of objects.

I am looking for assistance/advice on how to implement a button that allows the duplication of a selected row. I have successfully added a button that inserts a new row with dummy data generated within the addRow() function. The next step is to retrieve data from the selected row when the button is clicked. In my tableChanged() function I successfully retrieve the data changed, but it uses a TableModelEvent (when the table is edited) instead of an ActionEvent, which is used for my addRow() function. I need to find a way to have my ActionEvent detect my current row. Here is my code below:

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.event.*;
import javax.swing.table.TableModel;



public class MyTable extends JPanel implements TableModelListener,ActionListener {
    private boolean DEBUG = false;
    private JTable table;
    private MyTableModel model;
    private JButton duplicateButton;


    public MyTable() {
        super(new GridLayout(2,0));

        duplicateButton = new JButton("duplicate");
        JPanel pan = new JPanel(new BorderLayout());
        pan.add(duplicateButton);
        ArrayList<Entry> myEntries = new ArrayList<Entry>();

        Entry entry1 = new Entry(1, 116, "SOY", "test1", "code", "31122A", 1.0);
        Entry entry2 = new Entry(3, 118, "OATS", "test3", "code", "311230", 1.0);

        myEntries.add(entry1);
        myEntries.add(entry2);

        model = new MyTableModel(myEntries);
        table = new JTable(model);

        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);

        table.getModel().addTableModelListener(this);

        JScrollPane scrollPane = new JScrollPane(table);


        add(scrollPane);
        add(pan);

        duplicateButton.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        addRow();
    }

    public void tableChanged(TableModelEvent e) {
        int row = e.getFirstRow();
        int column = e.getColumn();
        TableModel tempmodel = (TableModel)e.getSource();
        //String columnName = model.getColumnName(column);
        Object data = tempmodel.getValueAt(row, column);

        System.out.println("**Table Change**");
        System.out.println("Row #: "+row);
        System.out.println("Column #: "+column);
        System.out.println("New Data: "+data);
        System.out.println("***************");

    }

    public void addRow(){
        Entry newEntry = new Entry(1, 120, "OATS", "testADD", "ADDcode", "311000", 1.0);
        ArrayList<Entry> temp = model.data;
        temp.add(newEntry);
        model.data = temp;
        //this.setModelData(temp);
        table.revalidate();
        table.repaint();

        model.fireTableDataChanged();
    }

    public class Entry{

        Object index;
        Object customer_id;
        Object expenditure_category;
        Object expenditure_description;
        Object commodity_classification;
        Object io_code;
        Object allocation;

        public Entry(Object i, Object c, Object ec, Object ed, Object cc, Object io, Double a){
            index = i;
            customer_id = c;
            expenditure_category = ec;
            expenditure_description = ed;
            commodity_classification = cc;
            io_code = io;
            allocation = a;
        }


        public Object find(int i){
            if(i == 0)
                return index;
            else if (i == 1)
                return customer_id;
            else if (i == 2)
                return expenditure_category;
            else if (i == 3)
                return expenditure_description;
            else if (i == 4)
                return commodity_classification;
            else if (i == 5)
                return io_code;
            else if (i == 6)
                return allocation;
            else
                return "No Value Found";
        }

        public void set(int i, Object x){
            if(i == 0)
                index = x;
            else if (i == 1)
                customer_id = x;
            else if (i == 2)
                expenditure_category = x;
            else if (i == 3)
                expenditure_description = x;
            else if (i == 4)
                commodity_classification = x;
            else if (i == 5)
                io_code = x;
            else if (i == 6)
                allocation = x;
        }


    }



    class MyTableModel extends AbstractTableModel {

        ArrayList<Entry> data;

        String [] columnNames = {"id", "customer_id","expenditure_category","expenditure_description","commodity_classification_code","io_code","allocation"};

        public MyTableModel(ArrayList<Entry> d){
            this.data = new ArrayList<Entry>(d);
        }

        /*
        Object[][] data = {
                {new Integer(1), new Integer(116), "SOY", "test1","code","31122A",new Double(1.0)},
                {new Integer(2), new Integer(116), "FIB", "test2","code","311990",new Double(1.0)},
                {new Integer(3), new Integer(118), "OATS", "test3","code","311230",new Double(1.0)},
                {new Integer(4), new Integer(118), "FLOUR", "V1","code","311210",new Double(.5)},
                {new Integer(5), new Integer(118), "FLOUR", "V2","code","311230",new Double(.5)},
                {new Integer(6), new Integer(118), "FIB", "test4","code","31123A",new Double(1.0)},
                {new Integer(7), new Integer(118), "FLOUR", "test5","code","31111B",new Double(1.0)},
                {new Integer(8), new Integer(118), "FLOUR", "test6","code","311000",new Double(1.0)}
        };
            */


        public int getColumnCount() {
            return columnNames.length;
        }

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

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            Entry e = this.data.get(row);
            return e.find(col);
        }


        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        public boolean isCellEditable(int row, int col) {

            if (col < 5) {
                return false;
            } else {
                return true;
            }
        }
        /*
        public void insertRow(int row, Entry e){

        }
        */


        public void setValueAt(Object value, int row, int col) {
            if (DEBUG) {
                System.out.println("Setting value at " + row + "," + col
                        + " to " + value
                        + " (an instance of "
                        + value.getClass() + ")");
            }
            Entry temp = data.get(row);

            temp.set(col, value);
            data.set(row,temp);
            fireTableCellUpdated(row, col);

            if (DEBUG) {
                System.out.println("New value of data:");
                printDebugData();
            }
        }


        private void printDebugData() {
            int numRows = getRowCount();
            int numCols = getColumnCount();

            for (int i=0; i < numRows; i++) {
                System.out.print("    row " + i + ":");
                for (int j=0; j < numCols; j++) {
                    //System.out.print("  " + data[i][j]);
                }
                System.out.println();
            }
            System.out.println("--------------------------");
        }
    }


    private static void createAndShowGUI() {

        JFrame frame = new JFrame("MyTable");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        MyTable newContentPane = new MyTable();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);


        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Solution

  • I have successfully created my duplicate button! After creating my button that added a row using an ActionListener, I retrieved the data from my table model using a RowListener, which implemented a ListActionListener.

    See the code below:

    import javax.swing.*;
    import javax.swing.table.AbstractTableModel;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    import javax.swing.event.*;
    import javax.swing.table.TableModel;
    
    
    
    
    public class SqlTable extends JPanel implements TableModelListener,ActionListener {
        private boolean DEBUG = false;
        private JTable table;
        private MyTableModel model;
        private JButton duplicateButton;
        private Entry selectedEntry;
        private boolean isSet = false;
        //Connector Vars
    
    
    
    public SqlTable() {
        super(new GridLayout(2,0));
    
        duplicateButton = new JButton("duplicate");
        JPanel pan = new JPanel(new BorderLayout());
        pan.add(duplicateButton);
        ArrayList<Entry> myEntries = new ArrayList<Entry>();
    
    
        Entry entry1 = new Entry("Customer1", "SOY", "test1", "code", "31122A", 1.0);
        Entry entry2 = new Entry("Customer2", "OATS", "test3", "code", "311230", 1.0);
    
        myEntries.add(entry1);
        myEntries.add(entry2);
    
        model = new MyTableModel(myEntries);
        table = new JTable(model);
    
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);
    
        table.getModel().addTableModelListener(this);
        table.getSelectionModel().addListSelectionListener(new RowListener());
    
        JScrollPane scrollPane = new JScrollPane(table);
    
    
        add(scrollPane);
        add(pan);
    
        duplicateButton.addActionListener(this);
    }
    
    public void actionPerformed(ActionEvent e) {
        addRow();
    }
    
    private class RowListener implements ListSelectionListener {
        public void valueChanged(ListSelectionEvent event) {
            if (event.getValueIsAdjusting()) {
                return;
            }
    
    
            int rowSelected = table.getSelectionModel().getLeadSelectionIndex();
            if(rowSelected!=-1) {
                ArrayList<Entry> temp = model.data;
                Entry tempEntry = temp.get(rowSelected);
                Object tempObj = tempEntry.find(5);
                Double tempDouble = (Double)tempObj;
                selectedEntry = new Entry(tempEntry.find(0),tempEntry.find(1),tempEntry.find(2),tempEntry.find(3),tempEntry.find(4),tempDouble);
                isSet = true;
    
                System.out.println("Row selected: "+table.getSelectionModel().getLeadSelectionIndex());
            }
    
        }
    }
    
    public void tableChanged(TableModelEvent e) {
        int row = e.getFirstRow();
        int column = e.getColumn();
        TableModel tempmodel = (TableModel)e.getSource();
        Object data = tempmodel.getValueAt(row, column);
    
        if(column!=-1){
    
    
    
    
    
            System.out.println("**Table Change**");
            System.out.println("Row #: "+row);
            System.out.println("Column #: "+column);
            System.out.println("New Data: "+data);
            System.out.println("***************");
        }
    
    }
    
    public void addRow(){
        if(isSet) {
            ArrayList<Entry> temp = model.data;
            temp.add(selectedEntry);
            model.data = temp;
            table.revalidate();
            table.repaint();
    
            model.fireTableDataChanged();
        }
    }
    
    public class Entry{
    
        Object name;
        Object expenditure_category;
        Object expenditure_description;
        Object commodity_classification;
        Object io_code;
        Object allocation;
    
        public Entry(Object n, Object ec, Object ed, Object cc, Object io, Double a){
            name = n;
            expenditure_category = ec;
            expenditure_description = ed;
            commodity_classification = cc;
            io_code = io;
            allocation = a;
        }
    
    
        public Object find(int i){
            if(i == 0)
                return name;
            else if (i == 1)
                return expenditure_category;
            else if (i == 2)
                return expenditure_description;
            else if (i == 3)
                return commodity_classification;
            else if (i == 4)
                return io_code;
            else if (i == 5)
                return allocation;
            else
                return "No Value Found";
        }
    
        public void set(int i, Object x){
            if(i == 0)
                name = x;
            else if (i == 1)
                expenditure_category = x;
            else if (i == 2)
                expenditure_description = x;
            else if (i == 3)
                commodity_classification = x;
            else if (i == 4)
                io_code = x;
            else if (i == 5)
                allocation = x;
        }
    
    
    }
    
    
    
    class MyTableModel extends AbstractTableModel {
    
        ArrayList<Entry> data;
    
        String [] columnNames = {"business_name","expenditure_category","expenditure_description","commodity_classification_code","io_code","allocation"};
    
        public MyTableModel(ArrayList<Entry> d){
            this.data = new ArrayList<Entry>(d);
        }
    
        public int getColumnCount() {
            return columnNames.length;
        }
    
        public int getRowCount() {
            return data.size();
        }
    
        public String getColumnName(int col) {
            return columnNames[col];
        }
    
        public Object getValueAt(int row, int col) {
            Entry e = this.data.get(row);
            return e.find(col);
        }
    
    
        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }
    
        public boolean isCellEditable(int row, int col) {
    
            if (col < 4) {
                return false;
            } else {
                return true;
            }
        }
    
        public void setValueAt(Object value, int row, int col) {
    
            if(col==4){
                String checkIOcode = value.toString();
                if(checkIOcode.length() == 6){
                    insertData(value,row,col);
                    ArrayList<Entry> temp = model.data;
                    Entry tempEntry = temp.get(row);
                    selectedEntry= tempEntry;
                }
            }else if(col==5) {
                String objectString = value.toString();
                if (isDecimal(objectString)||isNumeric(objectString)) {
                    Double checkAllocation = Double.parseDouble(objectString);
                    if (checkAllocation <= 1.0 && checkAllocation >= 0.0) {
                        insertData(value, row, col);
                        ArrayList<Entry> temp = model.data;
                        Entry tempEntry = temp.get(row);
                        selectedEntry= tempEntry;
                    }
                }
            }else{
                insertData(value,row,col);
                ArrayList<Entry> temp = model.data;
                Entry tempEntry = temp.get(row);
                selectedEntry= tempEntry;
            }
    
        }
    
        public boolean isDecimal(String s){
            String pattern= "^-?[0-9]*[.][0-9]*$";
            return s.matches(pattern);
        }
    
        public boolean isNumeric(String s){
            String pattern= "^-?[0-9]+$";
            return s.matches(pattern);
        }
    
        private void insertData(Object value, int row, int col){
            Entry temp = data.get(row);
    
            temp.set(col, value);
            data.set(row,temp);
            fireTableCellUpdated(row, col);
        }
    
    
        private void printDebugData() {
            int numRows = getRowCount();
            int numCols = getColumnCount();
    
            for (int i=0; i < numRows; i++) {
                System.out.print("    row " + i + ":");
                for (int j=0; j < numCols; j++) {
                    //System.out.print("  " + data[i][j]);
                }
                System.out.println();
            }
            System.out.println("--------------------------");
        }
    }
    
    private static void createAndShowGUI() {
    
        JFrame frame = new JFrame("SqlTable");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    
        SqlTable newContentPane = new SqlTable();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
    
    
        frame.pack();
        frame.setVisible(true);
    }
    
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
    }