2016-04-15 18 views
1

私は仕事のためにプロジェクトを進めていますが、私は珍しい問題に遭遇しました。私は、ユーザーがデータを入力できるJTableを持っています。私の実際のコードでは、ユーザーがいくつかのGUIを記入できるようにする行追加ボタンがあり、その情報が行を生成します。クローン作成後のJTableセルの編集

この重要なもう1つの機能は、行をクローンするボタンです。ユーザーが1つのセルで新しい行を追加するだけであれば、ボタンを使用してセルをクローンすることができるので、行を追加するプロセスは非常に時間がかかることがあります(記入するフィールドが多数あります)。

このクローンボタンは期待どおり機能しますが、かなり奇妙な問題があります。行がクローン化されると、クローンされた細胞の内容を変更しようとすると予期しない結果が生じることに気付きました。たとえば、セルの内容を「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); 



    } 

} 

答えて

3

あなたは同じ参照を再利用するのではなく、cloneメソッドに新しいオブジェクトをコピーしているように聞こえます。私は次のことをお勧めします。

1)まず、新しいベクターを作成し、それはそうのような、トリックを行いますかどうかを確認します。

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内の任意のクラスベースのオブジェクトに対して、現在あなたがポインタを扱っているそれらを再作成します。

ベクタの内容がわからないうちに#1が問題を解決できるかどうかはわかりませんが、プリミティブであればおそらく安全でしょう。それ以外の場合は解決策が必要な場合があります#2。そう、あなたが追加されている行が実際にある

dtm.insertRow(insertPoint, targetRow) 

を追加するときにコピーを作成していない

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

、あなたは新しい参照を作成している:

+0

私はあなたのテストで検証プログラム#1は、あなたの問題を解決します。根本的な問題は、Vectorへの参照を渡して複数の行に再利用することです。それは同じ根底にあるデータです。 –

+0

このソリューションは完全に機能しました。ご協力いただきありがとうございます。 – jesric1029

3

あなたの問題は、このラインでありますpreviosly選択された行と同じではなく、コピー。

あなたはそれを動作させるために

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

のようなものを使用する必要があります。

+0

私はそれを入力しようとすると、そのコードは動作しません.Clone()は有効なメソッドとして出てこない。 – jesric1029

+0

これは私の誤解です。私はベクターにする前に複製しようとしました。 今すぐお試しください – bns

+0

それは問題ありません。私はあなたが答えに時間がかかったので、まだあなたの答えをアップを与えました:) – jesric1029

2

クローンはここにキーワードです。あなたはデータを複製していません。あるベクトルから別のベクトルへ参照をコピーするだけです。したがって、各行が同じ参照を共有するので、値は両方の行に表示されます。

したがって、実際には各要素を複製する必要があります。あなたが使用することができるかもしれない前に、私はクローン()を使ったことがない

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

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

注::

コードは次のようなものになるだろう

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

が、私はよく分かりませんVector内の要素ではなく、Vectorをクローン化するだけです。

また、firstTableDataChanged()メソッドを呼び出すこともありません。これは、insertRow(...)メソッドが呼び出されたときに適切なメソッドを起動するDefaultTableModleの仕事です。

編集:

はい、クローンを使用して作業を行いますが、あなたがベクトルでない各アイテムベクトルのクローンを作成する必要があります。

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

または

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

トップコードは機能しません。最後のobject.cloneを使用しようとすると、「オブジェクトの型からclone()メソッドが見えない」というエラーが表示されます。 – jesric1029

+1

@ jesric1029、はい、あなたは正しいです。 :)しかし、2番目のアプローチはうまくいきますが、Vectorはclone()を実装していますので、直接呼び出すことができます。 – camickr

+0

心配することなく、私はあなたにup-voteを与えました。 – jesric1029

関連する問題