2009-10-31 5 views
22

高レベル:ユーザーがデータを編集するために使用できるJTableがあります。ユーザーがEnterキーを押すか、タブが編集を終了するたびJtableは、セルのフォーカスが失われるたびにデータを保存できますか?

、データが保存されている

ユーザーの葉であれば(私は「保存」というasusmingよ、本当に「のTableModelののsetValueAtを()メソッドが呼び出される」。意味します)セルは編集後に他の方法で保存されますが、新しいデータは保存されず、値は元のままです。たとえば、ユーザーが値を変更して画面上の他のウィジェットをクリックした場合、変更は「スティック」しません。

これはJTableのStringsでいっぱいのデフォルトの動作だと思いますか?

さまざまな理由から、セルがユーザーがセルを離れるたびにセルがすべての編集内容を保存することが望ましい動作です。これを行うためにスイングを取得するための最良の/正しい方法は何ですか?

答えて

5

focus listenerを追加する必要があります。 JTableは基本的にセルコンポーネントのコンテナであるため、実際には、指定した方法で動作する必要があるテーブル内のすべてのセルのフォーカスリスナーが必要です。

これを行うには、登録されたフォーカスリスナーを持つセルコンポーネントをラップするカスタムセルエディタを作成する必要があります。また、フォーカスイベントの喪失のコールバックを取得すると、必要に応じてデータを保存します。

This pretty much details most of what you need to do。フォーカスリスナーの実装の詳細はありませんが、それはかなり簡単です。

あなたは、セルコンポーネントとしてJTextComponentを使用します。次に:

public void focusLost(FocusEvent e) { 
    JTextComponent cell = (JTextComponent) e.getSource(); 
    String data = cell.getText(); 

    // TODO: save the data for this cell 
} 

[p.s.編集]:

このイベントであなたを呼び出しているスレッドがディスパッチスレッドです。待ち時間の長いアクションには使用しないでください。しかし、ヒープのビットを反転しているだけならOKです。

+0

2番目のリンクが機能していません。 : – Niroshan

+0

一時的なメディアに保存されている集合的知識の文脈で人類のために学ばれるレッスン – alphazero

+0

ウェイバックマシンはそれを持っていました。 –

14

簡単な解決策の1つは

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 

が唯一の文字列カラムに適して提案しました。問題は、たとえば、編集中の列の浮動小数点型がある場合、対応するセルに空の文字列を入力し、ウィンドウの他のコントロールをクリックすることです。NullPointerExceptionCellEditorRemover.propertyChange()メソッドJTable.javaにスローします。この場合はgetCellEditor()コールを使用して編集を中止またはキャンセルしますが、この場合はnullを返します。入力された値が空でない場合、またはterminateEditOnFocusLostフラグをすべて削除しても問題ありません。おそらく、説明されている状況はバグです。

私は前の投稿のいずれかに基づいて解決策を提供できることを願っています。それは私が前に仮定したようにそれほど些細なことではないが、それは私のように見える。 デフォルトのセルエディタから自分自身のセルエディタを継承し、JTextFieldのテキストフィールドはFocusListenerです。このフォーカスリスナーは、セルの編集でフォーカスが失われ、フォーカスがウィンドウの別のコントロールで取得されたときに正常に機能します。しかし、セル選択の変更の場合、フォーカスリスナーは「ろう者」である。そのため、入力値が無効であれば、復元を開始する前に以前は有効な値を覚えておく必要があります。

以下のコードを参照してください。 DoubleFloatIntegerでテストされましたが、これもByteStringで動作することを願っています。

フォーカスリスナーを持つテキストフィールド:

public class TextFieldCell extends JTextField { 
    public TextFieldCell(JTable cellTable) { 
     super();       // calling parent constructor 
     final JTable table = cellTable;  // this one is required to get cell editor and stop editing 

     this.addFocusListener(new FocusListener() { 
      public void focusGained(FocusEvent e) { 
      } 

      // this function successfully provides cell editing stop 
      // on cell losts focus (but another cell doesn't gain focus) 
      public void focusLost(FocusEvent e) { 
       CellEditor cellEditor = table.getCellEditor(); 
       if (cellEditor != null) 
        if (cellEditor.getCellEditorValue() != null) 
         cellEditor.stopCellEditing(); 
        else 
         cellEditor.cancelCellEditing(); 
      } 
     }); 
    } 
} 

デフォルトのセルエディタクラス:

class TextFieldCellEditor extends DefaultCellEditor { 
TextFieldCell textField; // an instance of edit field 
Class<?> columnClass;  // specifies cell type class 
Object valueObject;   // for storing correct value before editing 
public TextFieldCellEditor(TextFieldCell tf, Class<?> cc) { 
    super(tf); 
    textField = tf; 
    columnClass = cc; 
    valueObject = null; 
} 

@Override 
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
    TextFieldCell tf = (TextFieldCell)super.getTableCellEditorComponent(table, value, isSelected, row, column); 
    if (value != null) { 
     tf.setText(value.toString()); 
    } 
    // we have to save current value to restore it on another cell selection 
    // if edited value couldn't be parsed to this cell's type 
    valueObject = value; 
    return tf; 
} 

@Override 
public Object getCellEditorValue() { 
    try { 
     // converting edited value to specified cell's type 
     if (columnClass.equals(Double.class)) 
      return Double.parseDouble(textField.getText()); 
     else if (columnClass.equals(Float.class)) 
      return Float.parseFloat(textField.getText()); 
     else if (columnClass.equals(Integer.class)) 
      return Integer.parseInt(textField.getText()); 
     else if (columnClass.equals(Byte.class)) 
      return Byte.parseByte(textField.getText()); 
     else if (columnClass.equals(String.class)) 
      return textField.getText(); 
    } 
    catch (NumberFormatException ex) { 

    } 

    // this handles restoring cell's value on jumping to another cell 
    if (valueObject != null) { 
     if (valueObject instanceof Double) 
      return ((Double)valueObject).doubleValue(); 
     else if (valueObject instanceof Float) 
      return ((Float)valueObject).floatValue(); 
     else if (valueObject instanceof Integer) 
      return ((Integer)valueObject).intValue(); 
     else if (valueObject instanceof Byte) 
      return ((Byte)valueObject).byteValue(); 
     else if (valueObject instanceof String) 
      return (String)valueObject; 
    } 

    return null; 
} 

それはあなたが以下を追加する必要がテーブルの初期化のコード:

myTable.setDefaultEditor(Float.class, new TextFieldCellEditor(new TextFieldCell(myTable), Float.class)); 
myTable.setDefaultEditor(Double.class, new TextFieldCellEditor(new TextFieldCell(myTable), Double.class)); 
myTable.setDefaultEditor(Integer.class, new TextFieldCellEditor(new TextFieldCell(myTable), Integer.class)); 

・ホープこれは同じ問題を抱えている人を助けるでしょう。

関連する問題