数学、電気の勉強始めました!プログラムにも挑戦しています!|ω・)ノ

ねごとめも背景

# ねごとめも

# カウンター

# プロフィール

negotoy

Author:negotoy
電気の勉強始めました!
テキストエディタを使ってプログラミングに挑戦中。
fc2 ブログに公開しているテンプレート等は、自由にカスタマイズして、ご活用ください。
プログラム実行の前に必ずコードの確認をお願いします。

# 最新記事

# カレンダー

01 | 2013/02 | 03
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 - -

# スポンサードリンク

{ <pre></pre> タグ版のテキストエディタ作成しました }

前回の JTableクラス、複数行セル( JTextArea )の実装(1)[ キーアクション制御 ] を修正。
テストした範囲では動作は前回と同じ。
前回作成したプログラムは JTable と JTextArea 間でフォーカスのやり取りをしながら値を変更してた。
今回はテキストエリアにフォーカスを当てたままの状態でテーブルの値を変更するように修正。
修正してて気づいたのは、前回のは、望む値が出力されないと、その値を出力するためにコード追加。
追加してもまだ望む値が出力されないとコード追加。
その繰り返しでファイルサイズは大きくなるわ、ソースコードが汚くなるわの悪循環。
今回は、 ”テキストエリアへフォーカスを当てたままの状態での値の変更” を頭に置いといて書いたためか
少しだけファイルサイズも小さく、ソースコードも少しだけシンプルになった。
コードが汚く処理速度が遅くても望む結果が出力できればっ!\(^o^)/

FocusTest.java



import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

class FocusTest extends JFrame
{
	UndoRedoTable undoTable;
	static JTextArea textArea;
	FocusTest()
	{
		setTitle("Focus Test");
		setLookAndFeel();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		String[] header={"A","B","C"};
		String[][] tbody=
		{
			{"a-0","b-0","c-0"},
			{"a-1","b-1","c-1"},
			{"a-2","b-2","c-2"},
			{"a-3","b-3","c-3"}
		};
		getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.PAGE_AXIS));
		undoTable=new UndoRedoTable(tbody,header);
		JScrollPane scrollPane=new JScrollPane(undoTable);
		add(scrollPane);
		textArea=new JTextArea(50,100);
		textArea.setBorder(new LineBorder(Color.white,8,false));
		textArea.setText((String)undoTable.getValueAt(0,0));

		undoTable.setTextArea(textArea);
		JPanel menu=new JPanel();
		JLabel label=new JLabel("行:");
		Font font=new Font("Meiryo",Font.PLAIN,12);
		label.setFont(font);
		menu.add(label);
		JTextField[] textField=new JTextField[2];
		textField[0]=new JTextField("0",10);
		textField[0].setHorizontalAlignment(JTextField.RIGHT);
		textField[0].setEditable(false);
		menu.add(textField[0]);
		menu.add(Box.createRigidArea(new Dimension(30,1)));

		label=new JLabel("列:");
		label.setFont(font);
		menu.add(label);
		textField[1]=new JTextField("0",10);
		textField[1].setHorizontalAlignment(JTextField.RIGHT);
		textField[1].setEditable(false);
		menu.add(textField[1]);
		undoTable.setTextField(textField);
		add(menu);

		scrollPane=new JScrollPane(textArea);
		add(scrollPane);
		Dimension dimension=Toolkit.getDefaultToolkit().getScreenSize();
		int width=(int)dimension.getWidth();
		int height=(int)dimension.getHeight();
		setBounds((width-600)/2,(height-400)/2,600,400);
	}
	public static void main(String[] args)
	{
		new FocusTest().setVisible(true);
		textArea.requestFocus();
		String str=textArea.getText();
		textArea.setCaretPosition(str.length());
	}
	private void setLookAndFeel()
	{
		try
		{
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
			SwingUtilities.updateComponentTreeUI(this);
		}
		catch(Exception ex){}
	}
}

class UndoRedoTable extends JTable
{
	private JTextArea textArea;
	private JTextField[] textField;
	private boolean flg=true;
	UndoRedoTable(String[][] tbody,String[] header)
	{
		super(tbody,header);
		getTableHeader().setReorderingAllowed(false);
		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		//setDefaultEditor(Object.class,null);
		setColumnSelectionAllowed(true);
		setRowSelectionAllowed(true);
		//setSurrendersFocusOnKeystroke(true);
		//setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		//setRowHeight(getRowHeight()*2);
		for(int i=0;i<getColumnCount();i++)
		{
			getColumn(getColumnName(i)).setCellEditor(new TextAreaCellEditor());
		}
		setSelectionBackground(Color.red);
		//setFocusTraversalKeysEnabled(false);
		//KeyStroke tab=KeyStroke.getKeyStroke(KeyEvent.VK_TAB,0);
		//getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(tab,"none");
		//KeyStroke ctrl=KeyStroke.getKeyStroke(KeyEvent.CTRL_DOWN_MASK,0);
		//getInputMap(WHEN_FOCUSED).put(ctrl,"none");
		changeSelection(0,0,false,false);
		addMouseListener(new MouseAdapter()
		{
			public void mouseReleased(MouseEvent e)
			{
				UndoRedoTable tb=(UndoRedoTable)(e.getSource());
				int row=tb.getSelectedRow();
				int col=tb.getSelectedColumn();
				textField[0].setText(String.valueOf(row+1));
				textField[1].setText(String.valueOf(col+1));
				textArea.setText((String)tb.getValueAt(row,col));
				textArea.requestFocus();
			}
		});
		addKeyListener(new KeyAdapter()
		{
			public void Typed(KeyEvent e){}
			public void keyPressed(KeyEvent e){}
			public void keyReleased(KeyEvent e){}
		});
	}
	protected void setTextArea(JTextArea text)
	{
		textArea=text;
		textArea.setFocusTraversalKeysEnabled(false);
		//KeyStroke tab=KeyStroke.getKeyStroke(KeyEvent.VK_TAB,0);
		//textArea.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(tab,"none");
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//enter
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				row++;
				if(row==getRowCount()){ row=0; col++; }
				if(col==getColumnCount()){ col=0; }
				changeSelection(row,col,false,false);
				textArea.setText((String)getValueAt(row,col));
				System.out.println("enter");
			}
		});
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,InputEvent.SHIFT_DOWN_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//tab + shift
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				col--;
				if(col==-1){ col=getColumnCount()-1; row--; }
				if(row==-1){ row=getRowCount()-1; }
				changeSelection(row,col,false,false);
				textArea.setText((String)getValueAt(row,col));
				System.out.println("shift + tab");
			}
		});
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,InputEvent.CTRL_DOWN_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//tab + ctrl
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				col++;
				if(col==getColumnCount()){ col=0; row++; }
				if(row==getRowCount()){ row=0; }
				changeSelection(row,col,false,false);
				textArea.setText((String)getValueAt(row,col));
				System.out.println("ctrl + tab");
			}
		});
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,InputEvent.SHIFT_DOWN_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//enter + shift
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				row--;
				if(row==-1){ row=getRowCount()-1; col--; }
				if(col==-1){ col=getColumnCount()-1; }
				changeSelection(row,col,false,false);
				textArea.setText((String)getValueAt(row,col));
				System.out.println("shift + enter");
			}
		});
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,InputEvent.CTRL_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//enter + ctrl
			{
				JTextArea target=(JTextArea)e.getSource();
				target.insert("\n",target.getCaretPosition());
			}
		});
		textArea.addKeyListener(new KeyAdapter()
		{
			public void keyTyped(KeyEvent e){}
			public void keyPressed(KeyEvent e){}
			public void keyReleased(KeyEvent e)
			{

				int row=getSelectedRow();
				int col=getSelectedColumn();
				textField[0].setText(String.valueOf(row+1));
				textField[1].setText(String.valueOf(col+1));
				setValueAt(textArea.getText(),row,col);
			}
		});
		textArea.addInputMethodListener(new InputMethodListener()
		{
			@Override
			public void inputMethodTextChanged(InputMethodEvent event)
			{
				flg=(event.getText()==null)? true: false;
			}

			@Override
			public void caretPositionChanged(InputMethodEvent event){}
		});
	}
	public void setTextField(JTextField[] f)
	{
		textField=f;
	}
	@Override
	public Component prepareRenderer(TableCellRenderer tcr,int row,int column)
	{
		Component cmp=super.prepareRenderer(tcr,row,column);
		if(isCellSelected(row,column))
		{
			cmp.setForeground(getSelectionForeground());
			cmp.setBackground(getSelectionBackground());
		}
		else
		{
			cmp.setForeground(getForeground());
			cmp.setBackground(getBackground());
		}
		return cmp;
	}
}

class TextAreaCellEditor extends JTextArea implements TableCellEditor
{
	private final JScrollPane scroll;
	public TextAreaCellEditor()
	{
		scroll=new JScrollPane(this);
		setLineWrap(true);
		getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				stopCellEditing();
			}
		});
		getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,InputEvent.CTRL_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				insert("\n",getCaretPosition());
			}
		});
		addKeyListener(new KeyAdapter()
		{
			public void keyTyped(KeyEvent e){}
			public void keyPressed(KeyEvent e){}
			public void keyReleased(KeyEvent e){}
		});
	}
	@Override
	public Object getCellEditorValue()
	{
		return getText();
	}
	@Override
	public Component getTableCellEditorComponent(JTable table,Object value,boolean isSelected,int row,int column)
	{
		setFont(table.getFont());
		setText((value!=null)?value.toString():"");
		EventQueue.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				setCaretPosition(getText().length());
				requestFocusInWindow();
			}
		});
		return scroll;
	}
	@Override
	public boolean isCellEditable(final EventObject e)
	{
		return false;
	}
	transient protected ChangeEvent changeEvent=null;
	@Override
	public boolean shouldSelectCell(EventObject e)
	{
		return true;
	}
	@Override
	public boolean stopCellEditing()
	{
		fireEditingStopped();
		return true;
	}
	@Override
	public void cancelCellEditing()
	{
		fireEditingCanceled();
	}
	@Override
	public void addCellEditorListener(CellEditorListener l)
	{
		listenerList.add(CellEditorListener.class,l);
	}
	@Override
	public void removeCellEditorListener(CellEditorListener l)
	{
		listenerList.remove(CellEditorListener.class,l);
	}
	protected void fireEditingStopped()
	{
		Object[] listeners=listenerList.getListenerList();
		for(int i=listeners.length-2;i>=0;i-=2)
		{
			if(listeners[i]==CellEditorListener.class)
			{
				if(changeEvent == null){ changeEvent=new ChangeEvent(this); }
				((CellEditorListener)listeners[i+1]).editingStopped(changeEvent);
			}
		}
	}
	protected void fireEditingCanceled()
	{
		Object[] listeners=listenerList.getListenerList();
		for(int i=listeners.length-2;i>=0;i-=2)
		{
			if(listeners[i]==CellEditorListener.class)
			{
				if(changeEvent == null){ changeEvent=new ChangeEvent(this); }
				((CellEditorListener)listeners[i+1]).editingCanceled(changeEvent);
			}
		}
	}
}

JTableクラス、複数行セル( JTextArea )の実装(2)[ キーアクション制御 ]

参考にさせて頂いたサイト →  TableCellEditor をスクロール可能にする
上記サイトのサンプルは一つのサンプル中に色々な要素がてんこもり。
プログラムを読んで、実行して、クラスの作り方、メソッドの動作確認等ができるので勉強になります。

上記のサンプルを参考にさせて頂いて、JTableへ複数行セルの実装と、キーアクション制御テスト。
望む動作は、テキストエリア内でデータを編集、編集データを選択セルへ出力。
選択セルの値をテキストエリアへ出力。
テキストエリア内、 ctrl + enter キーで改行の挿入。
enter, shift + enter, shift + tab, ctrl + tab キーで の選択セルの移動。
マウス使用無しで、スムーズな編集ができるようにフォーカスイベントの処理。

ハマった場所は、 ctrl + tab キーの処理。
初期設定でキーが割り当ててあるのかな?
フォーカストラバーサルキーなるものの無効化と tab キー を無効化しないと、うまく動作してくれなかった。


setFocusTraversalKeysEnabled(false);//トラバーサルキー?の無効化
KeyStroke tab=KeyStroke.getKeyStroke(KeyEvent.VK_TAB,0);//tab キーの無効化
textArea.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(tab,"none");

んん??テキストエリアにフォーカスを当てたままの状態で選択セル移動、選択セルの内容変更が出来るのかな!?
もう少しやってみよう。(;´Д`)

■ 実行結果 ( テキストエリアの値はセルの値 )

JTableへの複数行セル実装

■ alt + tab キー実行結果 (初見)

alt + tab キー実行結果

■ FocusTest.java


import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

class FocusTest extends JFrame
{
	UndoRedoTable undoTable;
	static JTextArea textArea;
	FocusTest()
	{
		setTitle("Focus Test");
		setLookAndFeel();
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		String[] header={"A","B","C"};
		String[][] tbody=
		{
			{"a-0","b-0","c-0"},
			{"a-1","b-1","c-1"},
			{"a-2","b-2","c-2"},
			{"a-3","b-3","c-3"}
		};
		getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.PAGE_AXIS));
		undoTable=new UndoRedoTable(tbody,header);
		JScrollPane scrollPane=new JScrollPane(undoTable);
		add(scrollPane);
		textArea=new JTextArea(50,100);
		textArea.setBorder(new LineBorder(Color.white,8,false));
		textArea.setText((String)undoTable.getValueAt(0,0));
		undoTable.setTextArea(textArea);
		JPanel menu=new JPanel();
		JLabel label=new JLabel("行:");
		Font font=new Font("Meiryo",Font.PLAIN,12);
		label.setFont(font);
		menu.add(label);
		JTextField[] textField=new JTextField[2];
		textField[0]=new JTextField("0",10);
		textField[0].setHorizontalAlignment(JTextField.RIGHT);
		textField[0].setEditable(false);
		menu.add(textField[0]);
		menu.add(Box.createRigidArea(new Dimension(30,1)));
		label=new JLabel("列:");
		label.setFont(font);
		menu.add(label);
		textField[1]=new JTextField("0",10);
		textField[1].setHorizontalAlignment(JTextField.RIGHT);
		textField[1].setEditable(false);
		menu.add(textField[1]);
		undoTable.setTextField(textField);
		add(menu);
		scrollPane=new JScrollPane(textArea);
		add(scrollPane);
		Dimension dimension=Toolkit.getDefaultToolkit().getScreenSize();
		int width=(int)dimension.getWidth();
		int height=(int)dimension.getHeight();
		setBounds((width-500)/2,(height-350)/2,500,350);

	}
	public static void main(String[] args)
	{
		new FocusTest().setVisible(true);
		textArea.requestFocus();
		String str=textArea.getText();
		textArea.setCaretPosition(str.length());
	}
	private void setLookAndFeel()
	{
		try
		{
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
			SwingUtilities.updateComponentTreeUI(this);
		}
		catch(Exception ex){}

	}
}

class UndoRedoTable extends JTable
{
	private JTextArea textArea;
	private JTextField[] textField;
	UndoRedoTable(String[][] tbody,String[] header)
	{
		super(tbody,header);
		getTableHeader().setReorderingAllowed(false);
		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		setDefaultEditor(Object.class,null);
		setColumnSelectionAllowed(true);
		setRowSelectionAllowed(true);
		//setSurrendersFocusOnKeystroke(true);
		//setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		//setRowHeight(getRowHeight()*2);
		for(int i=0;i<getColumnCount();i++)
		{
			getColumn(getColumnName(i)).setCellEditor(new TextAreaCellEditor(this));
		}
		setSelectionBackground(Color.red);
		setFocusTraversalKeysEnabled(false);//フォーカストラバーサルキーの無効化
		KeyStroke tab=KeyStroke.getKeyStroke(KeyEvent.VK_TAB,0);//tabキーの無効化
		getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(tab,"none");
		changeSelection(0,0,false,false);
		addMouseListener(new MouseAdapter()
		{
			public void mouseReleased(MouseEvent e)
			{
				UndoRedoTable tb=(UndoRedoTable)(e.getSource());
				int row=tb.getSelectedRow();
				int col=tb.getSelectedColumn();
				textField[0].setText(String.valueOf(row));
				textField[1].setText(String.valueOf(col));
				textArea.setText((String)tb.getValueAt(row,col));
				textArea.requestFocus();
			}
		});
		addKeyListener(new KeyAdapter()
		{
			public void Typed(KeyEvent e){}
			public void keyPressed(KeyEvent e)
			{
				int keycode=e.getKeyCode();
				int mod=e.getModifiersEx();
				if((mod & InputEvent.SHIFT_DOWN_MASK)!=0&&keycode==KeyEvent.VK_ENTER)
				{
					System.out.println("shift + enter");
				}
				else if((mod & InputEvent.SHIFT_DOWN_MASK)!=0&&keycode==KeyEvent.VK_TAB)
				{
					System.out.println("shitf + tab");
				}
				else if((mod & InputEvent.CTRL_DOWN_MASK)!=0&&keycode==KeyEvent.VK_ENTER)
				{
					System.out.println("ctrl + enter");
				}
				else if((mod & KeyEvent.CTRL_DOWN_MASK)!=0&&keycode==KeyEvent.VK_TAB)
				{
					int row=getSelectedRow();
					int col=getSelectedColumn();
					col++;
					if(col==getColumnCount()){ col=0; row++; }
					if(row==getRowCount()){ row=0; }
					changeSelection(row,col,false,false);
					textArea.setText((String)getValueAt(row,col));
					System.out.println("ctrl + tab");
				}
				else if((keycode==KeyEvent.VK_ENTER))
				{
					System.out.println("enter");
				}
				else
				{
					textArea.requestFocus();
					System.out.println("other");
				}
			}
			public void keyReleased(KeyEvent e)
			{
				int keycode=e.getKeyCode();
				int mod=e.getModifiersEx();
				UndoRedoTable tb=(UndoRedoTable)(e.getSource());
				int row=tb.getSelectedRow();
				int col=tb.getSelectedColumn();
				textField[0].setText(String.valueOf(row));
				textField[1].setText(String.valueOf(col));
				textArea.setText((String)tb.getValueAt(row,col));
				if((mod & InputEvent.SHIFT_DOWN_MASK)!=0&&keycode==KeyEvent.VK_ENTER)
				{
					System.out.println("shift + enter");
				}
				else if((mod & InputEvent.SHIFT_DOWN_MASK)!=0&&keycode==KeyEvent.VK_TAB)
				{
					System.out.println("shitf + tab");
				}
				else if((mod & InputEvent.CTRL_DOWN_MASK)!=0&&keycode==KeyEvent.VK_ENTER)
				{
					System.out.println("ctrl + enter");
				}
				else if((mod & KeyEvent.CTRL_DOWN_MASK)!=0&&keycode==KeyEvent.VK_TAB)
				{
					System.out.println("ctrl + tab");
				}
				else if((keycode==KeyEvent.VK_ENTER))
				{
					System.out.println("enter");
					textArea.requestFocus();
				}
				else
				{
					textArea.requestFocus();
					System.out.println("other");
				}
			}
		});

	}
	void setTextArea(JTextArea text)
	{
		textArea=text;
		textArea.setFocusTraversalKeysEnabled(false);
		KeyStroke tab=KeyStroke.getKeyStroke(KeyEvent.VK_TAB,0);
		textArea.getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(tab,"none");
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//enter
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				row++;
				if(row==getRowCount()){ row=0; col++; }
				if(col==getColumnCount()){ col=0; }
				changeSelection(row,col,false,false);
				requestFocus();
			}
		});
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,InputEvent.SHIFT_DOWN_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//tab + shift
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				col--;
				if(col==-1){ col=getColumnCount()-1; row--; }
				if(row==-1){ row=getRowCount()-1; }
				changeSelection(row,col,false,false);
				requestFocus();
			}
		});
		textArea.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,InputEvent.CTRL_DOWN_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//tab + ctrl
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				col++;
				if(col==getColumnCount()){ col=0; row++; }
				if(row==getRowCount()){ row=0; }
				changeSelection(row,col,false,false);
				textArea.setText((String)getValueAt(row,col));
				requestFocus();
			}
		});
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,InputEvent.SHIFT_DOWN_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//enter + shift
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				row--;
				if(row==-1){ row=getRowCount()-1; col--; }
				if(col==-1){ col=getColumnCount()-1; }
				changeSelection(row,col,false,false);
				requestFocus();
			}
		});
		textArea.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,InputEvent.CTRL_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)//enter + ctrl
			{
				JTextArea target=(JTextArea)e.getSource();
				target.insert("\n",target.getCaretPosition());
			}
		});

		textArea.addKeyListener(new KeyAdapter()
		{
			public void keyTyped(KeyEvent e){}
			public void keyPressed(KeyEvent e)
			{
				int mod=e.getModifiersEx();
				if(((mod & InputEvent.CTRL_DOWN_MASK)!=0)&&e.getKeyCode()==KeyEvent.VK_TAB){}
			}
			public void keyReleased(KeyEvent e)
			{
				int row=getSelectedRow();
				int col=getSelectedColumn();
				setValueAt(getTextArea().getText(),row,col);
			}
		});
	}
	public JTextArea getTextArea()
	{
		return textArea;
	}

	public void setTextField(JTextField[] f)
	{
		textField=f;
	}
	public JTextField[] getTextField()
	{
		return textField;
	}
	@Override
	public Component prepareRenderer(TableCellRenderer tcr,int row,int column)
	{
		Component cmp=super.prepareRenderer(tcr,row,column);
		if(isCellSelected(row,column))
		{
			cmp.setForeground(getSelectionForeground());
			cmp.setBackground(getSelectionBackground());
		}
		else
		{
			cmp.setForeground(getForeground());
			cmp.setBackground(getBackground());
		}
		return cmp;
	}
}

class TextAreaCellEditor extends JTextArea implements TableCellEditor
{
	private final JScrollPane scroll;
	public TextAreaCellEditor(final UndoRedoTable table)
	{
		scroll=new JScrollPane(this);
		setLineWrap(true);
		getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				stopCellEditing();
			}
		});
		getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,InputEvent.CTRL_MASK),new AbstractAction()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				JTextArea target=(JTextArea)e.getSource();
				target.insert("\n",target.getCaretPosition());
			}
		});
		addKeyListener(new KeyAdapter()
		{
			public void keyTyped(KeyEvent e){}
			public void keyPressed(KeyEvent e){}
			public void keyReleased(KeyEvent e){}
		});
	}
	@Override
	public Object getCellEditorValue()
	{
		return getText();
	}
	@Override
	public Component getTableCellEditorComponent(JTable table,Object value,boolean isSelected,int row,int column)
	{
		setFont(table.getFont());
		setText((value!=null)?value.toString():"");
		EventQueue.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				setCaretPosition(getText().length());
				requestFocusInWindow();
			}
		});
		return scroll;
	}
	@Override
	public boolean isCellEditable(final EventObject e)
	{
		return false;
	}

	transient protected ChangeEvent changeEvent=null;
	@Override
	public boolean shouldSelectCell(EventObject e)
	{
		return true;
	}
	@Override
	public boolean stopCellEditing()
	{
		fireEditingStopped();
		return true;
	}
	@Override
	public void cancelCellEditing()
	{
		fireEditingCanceled();
	}
	@Override
	public void addCellEditorListener(CellEditorListener l)
	{
		listenerList.add(CellEditorListener.class,l);
	}
	@Override
	public void removeCellEditorListener(CellEditorListener l)
	{
		listenerList.remove(CellEditorListener.class,l);
	}

	protected void fireEditingStopped()
	{
		Object[] listeners=listenerList.getListenerList();
		for(int i=listeners.length-2;i>=0;i-=2)
		{
			if(listeners[i]==CellEditorListener.class)
			{
				if(changeEvent == null){ changeEvent=new ChangeEvent(this); }
				((CellEditorListener)listeners[i+1]).editingStopped(changeEvent);
			}
		}
	}
	protected void fireEditingCanceled()
	{
		Object[] listeners=listenerList.getListenerList();
		for(int i=listeners.length-2;i>=0;i-=2)
		{
			if(listeners[i]==CellEditorListener.class)
			{
				if(changeEvent == null){ changeEvent=new ChangeEvent(this); }
				((CellEditorListener)listeners[i+1]).editingCanceled(changeEvent);
			}
		}
	}
}

JTable と JTextArea を連動させた Undo Redo テスト。
望む動作は Jtable の選択モデル( セル )を変更した場合に UndoManager に変更を登録。
”元に戻す” , ”やり直し” ボタンで JTable の Undo Redo の実行。
選択セルに格納されているデータを JTextArea へ出力。

■ UndoManager(Swing)で紹介されてる テキスト以外のUNDO/REDOを参考にさせていただいて
色々テストしてみたけど、にんじゃばばんばん、理解できてない。(=_=;)
確認した範囲では望む動きはしてくれてんだけど、なんかあやしげ。
キーボードで選択セルの変更を行った場合は、 Undo Redo も正しく動いてくれるんだけど、
マウスでセル選択をした場合に、 Undo が正しく働かない時があったり、
登録するタイミングをうまく制御出来てないから
あれこれとコードを足して、一時しのぎ。晒しておきまふ。

■ 実行結果

にんじゃばばんばん(undo redo テスト)

■ UndoRedoTest.java


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEditSupport;

class UndoRedoTest extends JFrame
{
	UndoRedoTable undoTable;
	JTextArea textArea;
	UndoRedoTest()
	{
		setTitle("Undo Redo Test");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try
		{
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
			SwingUtilities.updateComponentTreeUI(this);
		}
		catch(Exception ex){}
		String[] header={"A","B","C","D","E","F"};
		String[][] tbody=
		{
			{"a-0","b-0","c-0","d-0","e-0","f-0"},
			{"a-1","b-1","c-1","d-1","e-1","f-1"},
			{"a-2","b-2","c-2","d-2","e-2","f-2"},
			{"a-3","b-3","c-3","d-3","e-3","f-3"}
		};
		JPanel contentPanel=new JPanel();
		getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.PAGE_AXIS));
		undoTable=new UndoRedoTable(tbody,header);
		JScrollPane scrollPane=new JScrollPane(undoTable);
		add(scrollPane);
		textArea=new JTextArea(50,100);
		textArea.setText((String)undoTable.getValueAt(0,0));
		undoTable.output(textArea);
		scrollPane=new JScrollPane(textArea);
		add(scrollPane);
		JPanel menu=new JPanel();
		JButton undo=new JButton("元に戻す");
		undo.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				if(undoTable.getUndoManager().canUndo()){ undoTable.getUndoManager().undo(); }
				if(undoTable.isDouble()&&undoTable.getUndoManager().canUndo()){ undoTable.getUndoManager().undo(); }
			}
		});
		menu.add(undo);
		JButton redo=new JButton("やり直し");
		redo.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				if(undoTable.getUndoManager().canRedo()){ undoTable.getUndoManager().redo(); }
				if(undoTable.isDouble()&&undoTable.getUndoManager().canRedo()){ undoTable.getUndoManager().redo(); }
			}
		});
		menu.add(redo);
		add(menu);
		Dimension dimension=Toolkit.getDefaultToolkit().getScreenSize();
		int width=(int)dimension.getWidth();
		int height=(int)dimension.getHeight();
		setBounds((width-600)/2,(height-400)/2,600,400);
		setVisible(true);
	}
	public static void main(String[] args)
	{
		new UndoRedoTest();
	}
}

class UndoRedoTable extends JTable
{
	private UndoableEditSupport undoSupport;
	private UndoManager undoManager=new UndoManager();
	private JTextArea textArea;
	private boolean flg;
	private int _row=0;
	private int _col=0;

	UndoRedoTable(String[][] tbody,String[] header)
	{
		super(tbody,header);
		getTableHeader().setReorderingAllowed(false);
		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		//setDefaultEditor(Object.class,null);
		setColumnSelectionAllowed(true);
		setRowSelectionAllowed(true);
		setSelectionBackground(Color.red);
		setSurrendersFocusOnKeystroke(true);
		//setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		changeSelection(0,0,false,false);
		undoSupport=new UndoableEditSupport(this);
		undoSupport.addUndoableEditListener(undoManager);
		undoSupport.postEdit(new SetCellUndoRedo(0,0));
		addMouseListener(new MouseAdapter()
		{
			public void mouseReleased(MouseEvent e)
			{
				UndoRedoTable tb=(UndoRedoTable)(e.getSource());
				int row=tb.getSelectedRow();
				int col=tb.getSelectedColumn();
				if(row==_row&&col==_col){ return; }
				if(!undoManager.canUndo())
				{
					undoSupport.postEdit(new SetCellUndoRedo(_row,_col));
				}
				undoSupport.postEdit(new SetCellUndoRedo(row,col));
				textArea.setText((String)tb.getValueAt(row,col));
				_row=row;
				_col=col;
			}
		});
		addKeyListener(new KeyAdapter()
		{
			public void keyReleased(KeyEvent e)
			{
				UndoRedoTable tb=(UndoRedoTable)(e.getSource());
				int row=tb.getSelectedRow();
				int col=tb.getSelectedColumn();
				undoSupport.postEdit(new SetCellUndoRedo(row,col));
				textArea.setText((String)tb.getValueAt(row,col));
			}
		});
	}
	public void output(JTextArea textArea)
	{
		this.textArea=textArea;
	}
	public boolean isDouble()
	{
		return flg;
	}
	public UndoManager getUndoManager()
	{
		return undoManager;
	}
	
	class SetCellUndoRedo extends AbstractUndoableEdit
	{
		private int row;
		private int col;
		SetCellUndoRedo(int row,int col)
		{
			this.row=row;
			this.col=col;
			//System.out.println("登録    row="+row+"    col="+col+"    _row="+_row+"    _col="+_col);
		}
		public void undo()
		{
			super.undo();
			UndoRedoTable.super.changeSelection(row,col,false,false);
			textArea.setText((String)getValueAt(row,col));
			flg=(row==_row&&col==_col)? true: false;
			_row=row;
			_col=col;
		}
		public void redo()
		{
			super.redo();
			UndoRedoTable.super.changeSelection(row,col,false,false);
			textArea.setText((String)getValueAt(row,col));
			flg=(row==_row&&col==_col)? true: false;
			_row=row;
			_col=col;
		}
	}
}

以前作成した、1000ページ以上のサイトマップ作成テスト(1) を利用してファイルの更新日時の取得テスト。

サイトマップの全ての lastmod の値がサイトマップ作成日の日付の出力から、
ファイルの更新日時を取得して、ファイル更新日の日付が出力されるように変更。
ファイルの更新日時の取得は、java.io.File の lastModified メソッドで取得。
戻り値を java.util.Date の引数へ渡す
SimpleDateFormatクラスを利用してフォーマットの作成。
Dateクラスの戻り値を java.text.SimpleDateFormat の format メソッドの引数へ渡す。

File file = new File("hoge.txt");
Date modified=new Date(file.lastModified());//ファイルの更新日時取得
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy'-'MM'-'dd");
String date=simpleDateFormat.format(modified);//2013-02-14

フレームがフォーカスを失うと背面へ回り込むのを無効にして、常に前面へ表示されるように変更。
java.awt.Window の setAlwaysOnTop メソッド引数へ true の値を渡す。
setAlwaysOnTop(true);

■ SiteMap.java


import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.TooManyListenersException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
class SiteMap extends JFrame
{
	String url="";
	SiteMap sitemap;
	JPopupMenu popUpMenu;
	public void alert(String str)
	{
		JLabel label=new JLabel(str);
		label.setFont(new Font("Meiryo",Font.PLAIN,12));
		label.setHorizontalAlignment(JLabel.CENTER);
		JOptionPane.showMessageDialog(sitemap,label);
	}
	public void mkSiteMap(List list) throws UnsupportedFlavorException,IOException
	{
		if(list.size()==1)
		{
			File file=(File)list.get(0);
			if(file.isDirectory())
			{
				try(BufferedReader input=new BufferedReader(new InputStreamReader(new FileInputStream(file.getParent()+"\\mySite.txt"),"utf-8")))
				{
					String line;
					int n=0;
					while((line=input.readLine())!=null)
					{
						if(n==0){ url=line+""; }
						n++;
					}
					input.close();
				}
				catch(FileNotFoundException error){}
				catch(IOException error){}
				String siteName=file.getName();
				sitemap.setTitle("サイト:"+siteName);
				StringBuffer result=new StringBuffer();
				result.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
				result.append("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n");
				ArrayList<File> tmpArray=new ArrayList<>();
				tmpArray.add(file);
				File[] fileArray=file.listFiles();
				tmpArray.addAll(Arrays.asList(fileArray));
				String absolutePath=file.getAbsolutePath();
				for(int i=0;i<tmpArray.size();i++)
				{
					file=tmpArray.get(i);
					if(i==0||!file.isDirectory()&&file.getAbsolutePath().indexOf("google")==-1)
					{
						if(i==0||file.getName().endsWith(".html")||file.getName().endsWith(".htm"))
						{
							Date modified=new Date(file.lastModified());//ファイルの更新日時取得
							SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy'-'MM'-'dd");
							String date=simpleDateFormat.format(modified);
							String changefreq=(i==0)?"daily":"weekly";
							String priority=(i==0)?"1.0":"0.5";
							String href=tmpArray.get(i).getAbsolutePath().replace("\\","/");
							if(!"".equals(url)){ href=href.replace(absolutePath.replace("\\","/"),url); }
							result.append("	<url>\n");
							result.append("		<loc>").append(href).append("</loc>\n");
							result.append("		<lastmod>").append(date).append("</lastmod>\n");
							result.append("		<changefreq>").append(changefreq).append("</changefreq>\n");
							result.append("		<priority>").append(priority).append("</priority>\n");
							result.append("	</url>\n");
						}
					}
					else if(file.isDirectory())
					{
						tmpArray.addAll(Arrays.asList(file.listFiles()));
					}
				}
				result.append("</urlset>\n");
				try(BufferedWriter output=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(absolutePath+"\\sitemap.xml"),"utf-8")))
				{
					output.write(result.toString().trim());
					output.close();
					alert("サイトマップ作成 [ "+siteName+" ]");
				}
			}
			else
			{
				alert("サイトマップ作成失敗");
			}
		}
		else
		{
			alert("サイトマップ作成失敗");
		}
	}
	SiteMap() throws Exception
	{
		sitemap=this;
		setAlwaysOnTop(true);//常に前面表示
		setTitle("sitemap");
		setLayout(new FlowLayout(FlowLayout.CENTER));
		JLabel label=new JLabel("フォルダの貼り付け、又はフォルダをドロップしてください。");
		label.setFont(new Font("Meiryo",Font.PLAIN,11));
		add(label);
		Dimension dimension=Toolkit.getDefaultToolkit().getScreenSize();
		int width=(int)dimension.getWidth();
		int height=(int)dimension.getHeight();
		setBounds((width-350)/2,(height-150)/2,350,150);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		addMouseListener(new MouseAdapter()
		{
			public void mousePressed(MouseEvent e)
			{
				if(javax.swing.SwingUtilities.isRightMouseButton(e))
				{
					if(popUpMenu==null)
					{
						Font font=new Font("Meiryo",Font.PLAIN,11);
						popUpMenu=new JPopupMenu();
						JMenuItem menuItem=new JMenuItem("サイトマップ作成");
						menuItem.setFont(font);
						menuItem.addActionListener(new ActionListener()
						{
							public void actionPerformed(ActionEvent evt)
							{
								Clipboard clipBoard=Toolkit.getDefaultToolkit().getSystemClipboard();
								Transferable transferable=clipBoard.getContents(null);
								try
								{
									List list=(List)transferable.getTransferData(DataFlavor.javaFileListFlavor);
									mkSiteMap(list);
								}
								catch(UnsupportedFlavorException e){ alert("サイトマップ作成失敗"); }
								catch(IOException e){ alert("サイトマップ作成失敗"); }
							}
						});
						popUpMenu.add(menuItem);
					}
					popUpMenu.show(e.getComponent(),e.getX()-4,e.getY()-6);
				}
			}
		});
		DropTarget dropTarget=new DropTarget();
		setDropTarget(dropTarget);
		try
		{
			dropTarget.addDropTargetListener(new DropTargetAdapter()
			{
				public void drop(DropTargetDropEvent evt)
				{
					evt.acceptDrop(DnDConstants.ACTION_COPY);
					try
					{
						Transferable transferble=evt.getTransferable();
						if(transferble.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
						{
							List list=(List)transferble.getTransferData(DataFlavor.javaFileListFlavor);
							mkSiteMap(list);
						}
					}
					catch(UnsupportedFlavorException dex){}
					catch(IOException dex){}
				}
			});
		}catch(TooManyListenersException e){}
	}
	public static void main(String[] args) throws Exception
	{
		new SiteMap().setVisible(true);
	}
}

PHPマニュアルを見てたら、ディレクトリ内の全ファイル削除の方法が紹介されてた。(・_・;)
PHP Manual unlink関数に掲載されてるコードを参考に、 以前作成した java プログラムを修正。
修正したら元のプログラムは跡形もなく消えてしまった。(-_-;)
こんな方法もあるの??って感じで、コードもシンプルで10行程度、
ArrayListクラスの配列に格納したり、キャストしたりすることもなし。
まだ先は長そうでう。

■ delete.java


import java.io.File;
public class delete
{
	public void removeDir(File file,boolean flg)
	{
		File[] fileArray=file.listFiles();
		for(int i=0;i<fileArray.length;i++)
		{
			if(!fileArray[i].delete()){ removeDir(fileArray[i],true); }
		}
		if(flg){ file.delete(); }
	}
	delete()
	{
		//削除する sample ディレクトリを指定、ディレクトリを削除しない場合は、第二引数へ false
		removeDir(new File("sample"),true);
	}
	public static void main(String[] args)
	{
		new delete();
	}
}

# スポンサードリンク