Java JTable 在复制行时出错

Java JTable mistake in copying rows

美好的一天! 下载的程序有问题。您可以通过鼠标右键单击它来复制一行,但是之后当您更改一个单元格中的数据时,列中每个单元格中的数据都会更改。请帮助我理解我错过了什么。

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.awt.BorderLayout;


import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;


public class Main extends JFrame{

    JMenuItem obrc;
    JTable table;
    DataModel tm;
    JScrollPane scrollTable;

    Main() {
         super("Example JTable");
         Container c = getContentPane();
         ArrayList<String> columnNames = new ArrayList<String>();
         columnNames.add("Type"); columnNames.add("Sort"); columnNames.add("Thickness"); columnNames.add("Width"); 
         tm = new DataModel(columnNames);
         table = new JTable(tm);
         c.add(new JScrollPane(table), BorderLayout.CENTER);
         setSize(400, 300);
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         setVisible(true);


        table.getColumnModel().getColumn(0).setPreferredWidth(40);
        table.getColumnModel().getColumn(1).setPreferredWidth(40);
        table.addMouseListener(new MouseAdapter(){
            public void mouseClicked(MouseEvent event) {
                if (SwingUtilities.isRightMouseButton(event)) {
                    JPopupMenu obrcd = new JPopupMenu();
                    obrc = new JMenuItem("Copy");
                    obrc.addActionListener(new MenuListener());
                    obrcd.add(obrc); 
                    obrcd.show(c, event.getX(), event.getY()); 
                }
            }
        });
    }

    public class MenuListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            int[] nums = table.getSelectedRows();
            if (nums.length != 0) {
                if (e.getSource() == obrc) {
                ArrayList<Object[]> list = tm.getRows(nums);
                tm.addRows(list);
                }

                else JOptionPane.showMessageDialog(null, 
                    "Select at least one row", "Warning", JOptionPane.ERROR_MESSAGE);
            }
        }
    }   


        public static void main(String[] args) {
            // TODO Auto-generated method stub
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new Main();

                }

            });
        }

        class DataModel extends AbstractTableModel{
              ArrayList<Object[]> data = new ArrayList<Object[]>();
              ArrayList<String> columnNames = new ArrayList<String>();

            public DataModel(ArrayList<String> cNames){
                super();
                columnNames = cNames;
                Object[] dat = new Object[4];
                dat[0] = "board";
                dat[1] = "1";
                dat[2] = "25";
                dat[3] = "150";
                data.add(dat);
            }

            public boolean isCellEditable(int rowIndex, int columnIndex)
            {
              return true;
            }

            public Object getValueAt(int rowIndex, int columnIndex){ 
                Object[] row = data.get(rowIndex);

                return row[columnIndex];
            };

            public void setValueAt(Object newValue, int rowIndex, int columnIndex){
                data.get(rowIndex)[columnIndex] = newValue;
                fireTableDataChanged();

            }

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

            public int getColumnCount()
            {
                return columnNames.size();
            };
            public String getColumnName(int column)
            {
                    return columnNames.get(column);
            }

            public ArrayList<Object[]> getRows(int[] nums) {
                ArrayList<Object[]> newdata = new ArrayList<Object[]>();
                for (int i = 0; i < nums.length; i++) {
                    newdata.add(data.get(nums[i]));
                }
                return newdata;
            }

            public void addRows (ArrayList<Object[]> rows) {
                for (int i = 0; i < rows.size(); i++) data.add(rows.get(i));
                fireTableDataChanged();
            }

        }
}

添加新行时出现问题

    public void addRows (ArrayList<Object[]> rows) {
        for (int i = 0; i < rows.size(); i++) data.add(rows.get(i));
        fireTableDataChanged();
    }

您复制的行将指向与所选行相同的对象。您需要克隆到新对象:

public void addRows (ArrayList<Object[]> rows) {
    for (int i = 0; i < rows.size(); i++) {
        Object[] clone = rows.get(i).clone();
        data.add(clone);
    }
    fireTableDataChanged();
}