8

私のアプリケーションでは、この例に似た Java テーブルを使用しています。私の問題は、セルの値を変更すると (上記の例でも)、別のセルをクリックするまでデータ モデルが更新されないことです。セルの値を変更した後、テーブルの下の灰色の領域をクリックしても、モデルは変更されません。その理由は、別のセルをクリックするまでセルがフォーカスされたままになっているためだと思います。これを回避し、テーブル セルをクリックせずにモデルを更新するにはどうすればよいですか。前もって感謝します

問題を反映するために上記のサンプルコードを編集しました

public class JTableDemo extends JApplet {
  private JTextArea txt = new JTextArea(4, 20);

  // The TableModel controls all the data:
  class DataModel extends AbstractTableModel {
    Object[][] data = { { "one", "two", "three", "four" },
        { "five", "six", "seven", "eight" },
        { "nine", "ten", "eleven", "twelve" }, };

    // Prints data when table changes:
    class TML implements TableModelListener {
      public void tableChanged(TableModelEvent e) {
        txt.setText(""); // Clear it
        for (int i = 0; i < data.length; i++) {
          for (int j = 0; j < data[0].length; j++)
            txt.append(data[i][j] + " ");
          txt.append("\n");
        }
      }
    }

    public DataModel() {
      addTableModelListener(new TML());
       fireTableDataChanged();
    }

    public int getColumnCount() {
      return data[0].length;
    }

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

    public Object getValueAt(int row, int col) {
      return data[row][col];
    }

    public void setValueAt(Object val, int row, int col) {
      data[row][col] = val;
      System.out.println(val);
      // Indicate the change has happened:
      fireTableDataChanged();
    }

    public boolean isCellEditable(int row, int col) {
      return true;
    }
  }

  public void init() {
    Container cp = getContentPane();
    JTable table = new JTable(new DataModel());
    cp.add(new JScrollPane(table));
    cp.add(BorderLayout.SOUTH, txt);
  }

  public static void main(String[] args) {
    run(new JTableDemo(), 350, 200);
  }

  public static void run(JApplet applet, int width, int height) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(applet);
    frame.setSize(width, height);
    applet.init();
    applet.start();
    frame.setVisible(true);
  }
}

例を実行すると、テーブルの下のテキスト領域にテーブルの内容が表示されます。セルを更新すると、下のテキスト ボックスに表示されます。ただし、「setValueAt」メソッドは、別のセルをクリックするまで呼び出されません。

4

3 に答える 3

13

これは予想される動作です: 編集された値は、明示的なユーザー ジェスチャ (Enter キーを押すか、タブで移動するか、テーブル内の他の場所をクリックするなど) まで、バッキング モデルにコミットされません ...

JTable の 1 つの奇妙な点 (バグと呼ぶ人もいます :-) は、テーブルの「外側」にフォーカスを移したときに、デフォルトでは編集が終了しないことです。強制的に実行するには、次のように構成する必要があります。

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

ところで(無関係、正気のために):常に最もきめ細かいイベントタイプを発生させます。ここでは、dataChangedハンマーの代わりにcellUpdatedになります。

于 2011-10-31T09:09:12.543 に答える
8

デフォルトの更新メカニズムは、セル エディターがフォーカスを失った場合にのみモデルを変更します。セルからタブで移動するか、別のセルをクリックすると、重要な「フォーカス喪失」イベントが発生し、モデルの変更がトリガーされます。

イベントを処理できるアクティブな要素がないため、灰色の領域をクリックしても効果はありません。テーブルはクリックを無視します。

これを変更したい場合は、ユーザーが「編集を終了した」ことをコンピュータに伝えるイベントを見つける必要があります。どうしてわかるの?

  • を追加できますActionListener( http://download.oracle.com/javase/tutorial/uiswing/components/textfield.htmlを参照)。RETURN を押すとトリガーされます。ハンドラーで、fireEditingStopped()「モデルへのコピー」コードをトリガーするために呼び出します ( http://download.oracle.com/javase/tutorial/uiswing/components/table.html#editorを参照)。
  • テーブルの下に「保存」ボタンを追加し、その中でこのコードを呼び出すことができますActionListner:

    if(null != jTable.getCellEditor()) {
        // there is an edit in progress
        jTable.getCellEditor().stopCellEditing()
    }
    
  • キープレス ハンドラーを追加することで、キープレスごとにモデルを更新できますが、エディターが表示されなくなる可能性があります。

[編集]「保存」ボタンを追加すると、ユーザーの編集「フロー」が中断される可能性があることに注意してください (表のセルをクリックする、編集する、マウスをつかむ、照準を合わせる、保存をクリックする、次のセルをクリックする、キーボードに戻る、編集する、...)

于 2011-10-31T09:16:19.407 に答える
0

私の場合

public void setValueAt(Object val, int row, int col) {
  data[row][col] = val;
  System.out.println(val);
  // Indicate the change has happened:
  fireTableDataChanged();
}

スーパー関数も呼び出す必要があります。

public void setValueAt(Object val, int row, int col) {
  data[row][col] = val;
  System.out.println(val);
  // Indicate the change has happened:
  fireTableDataChanged();
  super.setValueAt(val,row,col);
}
于 2020-04-14T16:52:50.587 に答える