簡體   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