近日为Cursor在JTable的单元格中移动问题,颇为苦恼,终于解决了。
但是有点遗憾,在把TabEditTable应用到JScrollPane上的时候,按下Tab键将Cursor移动到JTable的不可视区域时,
JScrollPane不能自动滚动了。
2004/12/09 不幸的消息:如果把这个table类放到滚动面板上,按下tab键当光标移动到不可见区域时,滚动条不
能自动滚动了。应该是FocusManager的问题。
解决中.........................................
/* パッケージの指定 */
package common.table;
/* パッケージのimport */
import javax.swing.*;
import javax.swing.FocusManager;
import javax.swing.table.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
* 編集されないセルにカーソルを移動しないテープル
* @version $Revision: 1.4 $ $Date: 2004/10/23 03:23:10 $
*/
public class TabEditTable extends JTable
{
protected boolean inTabbingEditor;
//protected FocusManager focusManager;
protected int[] editingColumns; // Model columns
protected int[] viewEditingColumns; // View columns
protected TabKeyListener tabKeyListener = new TabKeyListener();
/**デフォルトコンストラクタ*/
public TabEditTable()
{
super();
}
/**
* データモデル dm、デフォルト列モデル、デフォルト選択モデルで初期化される JTable を構築します。
* @param dm テーブルのデータモデル
*/
public TabEditTable(TableModel dm)
{
super(dm);
}
/**
* デフォルト選択モデルで初期化される JTable を構築します。
* @param dm テーブルのデータモデル
* @param cm テーブルの列モデル
*/
public TabEditTable(TableModel dm, TableColumnModel cm)
{
super(dm, cm);
}
/**
* 初期化される JTable を構築します。
* パラメータのどれかが null の場合、このメソッドは対応するデフォルトモデルでテーブルを初期化します。
* @param dm テーブルのデータモデル
* @param cm テーブルの列モデル
* @param sm テーブルの行選択モデル
*/
public TabEditTable(
TableModel dm,
TableColumnModel cm,
ListSelectionModel sm)
{
super(dm, cm, sm);
}
/**
* DefaultTableModel を使って、空のセルの numRows と numColumns で JTable を構築します。
* 列は、「A」、「B」、「C」といった形式の名前を持ちます。
* @param numRows テーブルが保持する行数
* @param numColumns テーブルが保持する列数
*/
public TabEditTable(int numRows, int numColumns)
{
super(numRows, numColumns);
}
/**
* Vectors の Vector の値を表示する JTable、つまり rowData を、列名 columnNames で構築します。
* rowData に格納された Vectors は、その行の値を保持しなければなりません。
* つまり、行 1、列 5 に位置するセルの値は次のコードで取得できます。
* @param rowData 新しいテーブルのデータ
* @param columnNames 各列の名前
*/
public TabEditTable(final Vector rowData, final Vector columnNames)
{
super(rowData, columnNames);
}
/**
* 2 次元配列 rowData の値を表示する JTable を、列名 columnNames で構築します。
* rowData は行の配列なので、行 1、列 5 に位置するセルの値は次のコードで取得できます。
* rowData[1][5]; すべての行は、columnNames と同じ長さでなければなりません。
* @param rowData 新しいテーブルのデータ
* @param columnNames 各列の名前
*/
public TabEditTable(final Object[][] rowData, final Object[] columnNames)
{
super(rowData, columnNames);
}
/**
* editingColumns 変数を設定します。
* @param columns
*/
public void setEditingColumns(int[] columns)
{
editingColumns = columns;
convertEditableColumnsToView();
}
/**
* editingColumns 変数を取得します。
* @return
*/
public int[] getEditingColumns()
{
return editingColumns;
}
/**
* Overrides of JTable methods
* row および column に位置するセルが編集可能な場合は、編集をプログラムに基づいて開始します。
* @param row 編集する行
* @param column 編集する列
* @param evt イベント
*/
public boolean editCellAt(int row, int column, EventObject evt)
{
if (super.editCellAt(row, column, evt) == false)
{
return false;
}
if (viewEditingColumns != null)
{
// Note: column is specified in terms
// of the column model
int length = viewEditingColumns.length;
for (int i = 0; i < length; i++)
{
if (column == viewEditingColumns[i])
{
Component comp = getEditorComponent();
comp.addKeyListener(tabKeyListener);
this.addKeyListener(tabKeyListener);
//focusManager = FocusManager.getCurrentManager();
//FocusManager.disableSwingFocusManager();
inTabbingEditor = true;
comp.requestFocus();
break;
}
}
}
return true;
}
/**
* 編集が完了したときに呼び出されます。変更は保存され、エディタは破棄されます。
* @param evt 受け取ったイベント
*/
public void editingStopped(ChangeEvent evt)
{
if (inTabbingEditor == true)
{
Component comp = getEditorComponent();
comp.removeKeyListener(tabKeyListener);
this.removeKeyListener(tabKeyListener);
//FocusManager.setCurrentManager(focusManager);
inTabbingEditor = false;
}
super.editingStopped(evt);
}
/**
* フォーカスを移動処理を制御
*/
protected void convertEditableColumnsToView()
{
// Convert the editable columns to view column numbers
if (editingColumns == null)
{
viewEditingColumns = null;
return;
}
// Create a set of editable columns in terms of view
// column numbers in ascending order. Note that not all
// editable columns in the data model need be visible.
int length = editingColumns.length;
viewEditingColumns = new int[length];
int nextSlot = 0;
for (int i = 0; i < length; i++)
{
int viewIndex = convertColumnIndexToView(editingColumns[i]);
if (viewIndex != -1)
{
viewEditingColumns[nextSlot++] = viewIndex;
}
}
// Now create an array of the right length
// to hold the view indices
if (nextSlot < length)
{
int[] tempArray = new int[nextSlot];
System.arraycopy(viewEditingColumns, 0, tempArray, 0, nextSlot);
viewEditingColumns = tempArray;
}
// Finally, sort the view columns into order
TableUtilities.sort(viewEditingColumns);
}
/**
* 後ろのエディタへフォーカスを移動する
* @param row
* @param column
* @param forward
*/
protected void moveToNextEditor(int row, int column, boolean forward)
{
// Column is specified in terms of the column model
if (viewEditingColumns != null)
{
int length = viewEditingColumns.length;
// Move left-to-right or right-to-left
// across the table
for (int i = 0; i < length; i++)
{
if (viewEditingColumns[i] == column)
{
// Select the next column to edit
if (forward == true)
{
if (++i == length)
{
// Reached end of row - wrap
i = 0;
row++;
if (row == getRowCount())
{
// End of table - wrap
row = 0;
}
}
} else
{
if (--i < 0)
{
i = length - 1;
row--;
if (row < 0)
{
row = getRowCount() - 1;
}
}
}
final int newRow = row;
final int newColumn = viewEditingColumns[i];
// Start editing at new location
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
editCellAt(newRow, newColumn);
ListSelectionModel rowSel = getSelectionModel();
ListSelectionModel columnSel =
getColumnModel().getSelectionModel();
rowSel.setSelectionInterval(newRow, newRow);
columnSel.setSelectionInterval(
newColumn,
newColumn);
}
});
break;
}
}
}
}
// Catch changes to the table column model
public void columnAdded(TableColumnModelEvent e)
{
super.columnAdded(e);
convertEditableColumnsToView();
}
public void columnRemoved(TableColumnModelEvent e)
{
super.columnRemoved(e);
convertEditableColumnsToView();
}
public void columnMoved(TableColumnModelEvent e)
{
super.columnMoved(e);
convertEditableColumnsToView();
}
/**
* タプキーリスナー
* 後ろのエディタへフォーカスを移動する
*/
public class TabKeyListener extends KeyAdapter
{
public void keyPressed(KeyEvent evt)
{
if (evt.getKeyCode() == KeyEvent.VK_TAB)
{
if (inTabbingEditor == true)
{
TableCellEditor editor = getCellEditor();
int editRow = getEditingRow();
int editColumn = getEditingColumn();
if (editor != null)
{
boolean stopped = editor.stopCellEditing();
if (stopped == true)
{
boolean forward = (evt.isShiftDown() == false);
moveToNextEditor(editRow, editColumn, forward);
}
}
}
} else {
if ( evt.getKeyCode() == KeyEvent.VK_RIGHT) {
if (inTabbingEditor == true) {
TableCellEditor editor = getCellEditor();
int editRow = getEditingRow();
int editColumn = getEditingColumn();
if (editor != null) {
boolean stopped = editor.stopCellEditing();
if (stopped == true) {
boolean forward = (evt.isShiftDown() == false);
moveToNextEditor(editRow, editColumn, forward);
}
}
}
} else if ( evt.getKeyCode() == KeyEvent.VK_LEFT ) {
if (inTabbingEditor == true) {
TableCellEditor editor = getCellEditor();
int editRow = getEditingRow();
int editColumn = getEditingColumn();
if (editor != null) {
boolean stopped = editor.stopCellEditing();
if (stopped == true) {
boolean forward = (evt.isShiftDown() == true);
moveToNextEditor(editRow, editColumn, forward);
}
}
}
}
}
}
}
}