繁体   English   中英

克隆后编辑JTable单元

[英]Editing JTable cells after being cloned

我正在为一个工作项目工作,但遇到了一个异常问题。 我有一个JTable,用户可以在其中填充数据。 在我的实际代码中,有一个“添加行”按钮,该按钮使用户可以填写一些GUI,而该信息将生成该行。

此功能的另一个重要功能是用于克隆行的按钮。 由于添加一行的过程可能非常耗时(有许多字段需要填写),如果用户只需要添加一个新行,但其中的一个单元格不同,那么他可以使用按钮克隆该单元格。

此克隆按钮按预期工作,但是存在一个相当奇怪的问题。 克隆一行后,我注意到当我尝试更改已克隆的任何单元格的内容时,会出现意外结果。 例如,如果我将一个单元格的内容更改为“ Ryan”,则其他单元格也可能会突然更改,并且如果我在更改一个单元格后甚至单击某个单元格,我单击的单元格也会自行更改。 我非常确定这个问题与克隆方法有关,我只是真的不知道要解决什么。

我创建了一个可验证的程序,以便您可以自己发短信并查看我在说什么。 只需几次使用克隆按钮,然后尝试更改单个单元格的内容并在其他单元格中观察结果。

我确实需要解决此问题,但是我对如何做一无所知,我们非常感谢您的帮助。

主班

package jtabletest;

public class JTableTestMain 

{

    public static void main(String args[]){

        JTableTest jTest = new JTableTest();
        jTest.createGUI();

    }

}

JTable类

package jtabletest;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class JTableTest 

{

    protected static DefaultTableModel dtm = new DefaultTableModel();
    public static JTable tbl;


    public void createGUI(){

        final JFrame frame = new JFrame("JTable Test");
        JPanel mainPanel = new JPanel(new BorderLayout());
        JPanel panelNorth = new JPanel(new BorderLayout());
        JPanel panelSouth = new JPanel(new BorderLayout());
        JPanel buttonPanel = new JPanel();

        JButton cloneButton = new JButton("Clone");
        cloneButton.setPreferredSize(new Dimension(150,40));
        buttonPanel.add(cloneButton);

        JButton printButton = new JButton("Print");
        printButton.setPreferredSize(new Dimension(150,40));
        buttonPanel.add(printButton);

        tbl = new JTable();

        String header[] = new String[]{
                "Employee", "Pay-Rate", "Hours Worked"};


        dtm.setColumnIdentifiers(header);

        tbl.setModel(dtm);

        tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        for(int i = 0; i < header.length; i++){
            tbl.getColumnModel().getColumn(i).setPreferredWidth(200);
        }

        dtm.addRow(new Object[]{"Pete","$10.00","40"});
        dtm.addRow(new Object[]{"Bob","12.50","42"});
        dtm.addRow(new Object[]{"Jamar","$7.25,25"});

        cloneButton.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent ae){

                int[] selectedRows = tbl.getSelectedRows();

                if(selectedRows.length>0){

                    @SuppressWarnings("rawtypes")
                    Vector data = dtm.getDataVector();

                    int insertPoint = selectedRows[selectedRows.length-1]+1;

                    for(int i = 0; i < selectedRows.length; i++){
                        @SuppressWarnings("rawtypes")
                        Vector targetRow = (Vector)data.elementAt(selectedRows[i]);

                        dtm.insertRow(insertPoint, targetRow);
                        insertPoint++;

                    }

                    dtm.fireTableDataChanged();

                }

            }

        });

        printButton.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent ae){

                if(null != tbl.getCellEditor()){
                    tbl.getCellEditor().stopCellEditing();
                }

                for(int i = 0; i < tbl.getRowCount(); i++){
                    System.out.println(tbl.getValueAt(i, 0));
                    System.out.println(tbl.getValueAt(i, 1));
                    System.out.println(tbl.getValueAt(i, 2));
                }

            }

        });

        panelNorth.add(tbl,BorderLayout.NORTH);
        panelNorth.setPreferredSize(new Dimension(500,500));
        panelSouth.add(buttonPanel,BorderLayout.NORTH);
        mainPanel.add(panelNorth,BorderLayout.NORTH);
        mainPanel.add(panelSouth,BorderLayout.SOUTH);
        frame.add(mainPanel);
        frame.setVisible(true);
        frame.setSize(1900,600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



    }

}

听起来您正在重用相同的引用,而不是在clone方法上复制新对象。 我建议做以下事情。

1)首先创建一个新的Vector,看看是否可以解决问题,就像这样。

for(int i = 0; i < selectedRows.length; i++){
  @SuppressWarnings("rawtypes")
  Vector targetRow = (Vector)data.elementAt(selectedRows[i]);
  Vector newVector = new Vector();
  for (int t = 0; t < targetRow.size(); t++) {
     newVector.add(targetRow.get(t));
  }
  dtm.insertRow(insertPoint, newVector);
  insertPoint++;
}

看看这是否可以解决您的问题。 如果是这样,您就完成了。 如果不是这样

2)创建一个类似于上面的新Vector,为Vector中的任何基于Class的对象重新创建它们,因为当前您正在处理指针。

我很难说#1是否可以解决您的问题,因为我不知道来自表的Vector的内容,如果它是原语,则可能是安全的,否则您可能需要执行解决方案#2。

您的问题在这一行:

Vector targetRow = (Vector)data.elementAt(selectedRows[i]);

您不是要创建副本,而是要创建新的引用,因此添加时

dtm.insertRow(insertPoint, targetRow)

您要添加的行实际上是相同的,而不是先前选择的行的副本。

您将不得不使用类似

Vector aux = (Vector)data.elementAt(selectedRows[i]);
Vector targetRow = aux.clone();

使它工作。

克隆是此处的关键字。 您没有克隆数据。 您只是将引用从一个Vector复制到另一个。 因此,由于每一行共享相同的引用,因此该值将出现在两行中。

因此,您实际上需要克隆每个元素。

该代码将类似于:

  Vector targetRow = (Vector)data.elementAt(selectedRows[i]);
  Vector clonedRow = new Vector(targetRow.size());

  for (Object object: targetRow)
  {
     clonedRow.addElement( object.clone() );
  }

注意,我之前从未使用过clone(),因此您可以使用:

  Vector targetRow = (Vector)data.elementAt(selectedRows[i]);
  Vector clonedRow = targetRow.clone();

但是我不确定是否只是克隆Vector而不克隆Vector中的元素。

另外,您永远不会调用firstTableDataChanged()方法。 这是DefaultTableModle的工作,可以在调用insertRow(...)方法时触发适当的方法。

编辑:

是的,使用克隆确实可以,但是您需要克隆Vector而不是Vector中的每个项目:

//dtm.insertRow(insertPoint, targetRow);
dtm.insertRow(insertPoint, (Vector)targetRow.clone());

要么

dtm.insertRow(insertPoint, new Vector(targetRow));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM