プロが教えるわが家の防犯対策術!

JTable で複数行の編集ができるようにしたいと思っています。
JTextArea を使う独自の CellEditor を作ることで、できました。

ただ、編集を開始するのにマウスでダブルクリックする必要があります。
セルにフォーカスがある状態で、キーボード入力で編集を開始できないでしょうか?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

JTextField を使った DefaultCellEditor はできます。
自作の JTextArea を使う CellEditor でもできました。
しかし、JScrollPane を付けるとできなくなります。

解決策をご存知の方がいらっしゃいましたら、よろしくお願いします。

public class TextAreaCellEditor extends AbstractCellEditor implements
TableCellEditor {

private JTextArea textArea = new JTextArea();
private JScrollPane scroll = new JScrollPane(textArea);

public TextAreaCellEditor() {
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
}

public Object getCellEditorValue() {
return textArea.getText();
}

public boolean isCellEditable(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
return ((MouseEvent) anEvent).getClickCount() >= 2;
}
return true;
}

public boolean shouldSelectCell(EventObject anEvent) {
return true;
}

public boolean stopCellEditing() {
fireEditingStopped();
return true;
}

public void cancelCellEditing() {
fireEditingCanceled();
}

public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
textArea.setText((value != null) ? value.toString() : "");
return scroll;
// JScrollPane を付けなければ可能
// return textArea;
}
}

A 回答 (3件)

> セルにフォーカスがある状態で、


TABキーによる遷移のことなら、テーブルのアクションマップに新しいTABアクション(テキストエリアがキーフォーカスを取得する)を登録する必要があります。最初に、既存のアクションも呼び出す必要があるでしょうね。
    • good
    • 0
この回答へのお礼

_ranco_さん、ご回答ありがとうございます。
教えてもらったことをヒントに、F2キーを押すと編集できるように
なりました。
以下のような感じです。

---
ActionMap am = table.getActionMap();
final Action oldStartEditingAction = am.get("startEditing");
AbstractAction startEditingAction = new AbstractAction() {
  public void actionPerformed(ActionEvent e) {
    oldStartEditingAction.actionPerformed(e);
    textArea.requestFocus();
  }
};
am.put("startEditing", startEditingAction);
---

理想をいうと、F2キーを押さなくても編集状態に
なってくれるといいんですけど。

TABキーは、"selectNextColumnCell" アクションを置き換えることに
なると思いますが、これはうまくいきませんでした。
それに、TABキーだけじゃなく、矢印キーで遷移した場合も
編集可能になってほしいです。

何か方法はないでしょうか?

お礼日時:2008/04/14 14:00

次のようにすれば、テキストエリアにフォーカスを与えることができます:


--------------------------------------------------------------------
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class TextAreaCellEditor extends AbstractCellEditor implements
TableCellEditor, TableCellRenderer {
 private JTextArea textArea;
 private JScrollPane scroll;

 public TextAreaCellEditor() {
  textArea = new JTextArea();
  scroll = new JScrollPane(textArea);
 }

 public JTextArea getTextArea(){
  return textArea;
 }

 public Object getCellEditorValue() {
  return textArea.getText();
 }

 public boolean shouldSelectCell(EventObject anEvent) {
  return true;
 }

 public boolean stopCellEditing() {
  fireEditingStopped();
  return true;
 }

 public void cancelCellEditing() {
  fireEditingCanceled();
 }

 public Component getTableCellEditorComponent(JTable table, Object value,
   boolean isSelected, int row, int column) {
  textArea.setText((value != null) ? value.toString() : "");
  textArea.setCaretPosition(textArea.getText().length());
  return scroll;
 }

 public Component getTableCellRendererComponent(JTable table,
  Object value, boolean isSelected, boolean hasFocus, int row, int column){
  textArea.setText((value != null) ? value.toString() : "");
  textArea.setCaretPosition(textArea.getText().length());
  return scroll;
 }

 static void focusOnTextArea(JTable table){
  InputMap im
   = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);

  final Action oldTabAction = table.getActionMap().get(im.get(tab));
  Action tabAction = new AbstractAction(){
   public void actionPerformed(ActionEvent e){
    oldTabAction.actionPerformed(e);
    JTable table = (JTable)e.getSource();

    int row = table.getSelectedRow();
    int column = table.getSelectedColumn();
    if (column == 1){ // このセルエディタのカラムだ
     table.editCellAt(row, column); // 強制的にエディットモードにする
     TextAreaCellEditor tace
      = (TextAreaCellEditor)(table.getCellEditor(row, column));
     JTextArea ta = tace.getTextArea();
     ta.requestFocusInWindow(); // テキストエリアにキーフォーカス
    }
   }
  };
  table.getActionMap().put(im.get(tab), tabAction);

  // 右矢印キーも使いたい
  KeyStroke right = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);
  im.put(right, im.get(tab));
 }

 /* test */
 public static void main(String[] args){
  JFrame frame = new JFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  Container con = frame.getContentPane();

  JTable table = new JTable(20, 3);
  table.setRowHeight(70);
  JScrollPane jsp = new JScrollPane(table);
  con.add(jsp, BorderLayout.CENTER);

  TextAreaCellEditor tace = new TextAreaCellEditor();
  TableColumn tc = table.getColumn(table.getColumnName(1));
  tc.setCellEditor(tace); // for column 1
  tc.setCellRenderer(tace);

  focusOnTextArea(table);

  frame.pack();
  frame.setVisible(true);
 }
}
    • good
    • 0
この回答へのお礼

ありがとうございます。
「強制的にエディットモードにする」ことができるなんて
知りませんでした。
参考にさせていただきます。

お礼日時:2008/05/02 17:50

amのget()に具体的な名前ではなくInputMap.get()の結果をそのまま渡したほうがいいですね。

だいたいのストーリーは、次のようになるでしょう:
------------------------------------------------
InputMap im
= table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
...
KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
...
final Action oldTabAction = table.getActionMap().get(im.get(tab));
Action tabAction = new AbstractAction(){
 public void actionPerformed(ActionEvent e){
  oldTabAction.actionPerformed(e);
  ...
  ...
  ...
  ...
 }
}
...
table.getActionMap().put(im.get(tab), tabAction);
...
KeyStroke right = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);
im.put(right, im.get(tab));
------------------------------------------------
    • good
    • 0
この回答へのお礼

InputMap.get()の結果をそのまま渡しても、編集可能には
なってくれませんでした。
#textArea.requestFocus()だけじゃダメなのかな
F2キーが使えるようになったので、今回はこれでよしとします。
ご回答ありがとうございました。

お礼日時:2008/04/22 14:05

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!