テキストエディタの作り方:Swingのフォーカスについて
あー、本来ならJavaで書くべきでしょうが、Scalaでjavax.swingを使ってます。m(_ _)m
テキストエディタやバイナリエディタを作ろうとしたとき、そのビューに対してキーイベントを 受け付けるようにしなければなりません。
キーイベントに関しては、イベントマスクを外してやる必要があります。
また、TABキーはデフォルトでは、別のコンポーネントにフォーカスが移ってしまうので、 TABキーのイベントは来ません。 TABキーをイベントとして欲しい場合は、フォーカスマネージャの設定を変える必要があります。
import java.awt.{AWTEvent,AWTKeyStroke,KeyboardFocusManager} class TextView(val model:TextModel) extends JComponent { // フォーカスを与える > enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.INPUT_METHOD_EVENT_MASK) > setFocusable(true) // TABでフォーカスが移らないように、デフォルトのフォーカス移動キーを変更。 > setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, new java.util.HashSet[AWTKeyStroke]()) > setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, new java.util.HashSet[AWTKeyStroke]()) > setFocusTraversalKeys(KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, new java.util.HashSet[AWTKeyStroke]()) // マウスカーソルをIビームに > setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)) // キーリスナー、マウスリスナーを登録 > addKeyListener(new EditorKeyListener()) ... }
それと、Swingアプリケーションを立ち上げたとき、最初のフォーカスの位置は、 左上のコンポーネントになります。
一般的なアプリならば、ツールバーの左端のボタンになるでしょうか。 望みのビューに最初にフォーカスを与えるには、以下のようにします。
class TextFrame extends JFrame { def addTab(title:String, tip:String, model:TextModel) { println("addTab(title="+title+")") val tab = new TextTab(model) tabPane.addTab(title, null, tab, tip) tabPane.setSelectedIndex(tabPane.getTabCount() - 1) // ビューにフォーカスを移す > this.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() { > override def getInitialComponent(w:java.awt.Window):java.awt.Component = { > tab.focusView > } > }) } }
テキスト編集ビューでマウスをクリックしたとき、そのビューにフォーカスを移したい場合があります。 例えば、分割ビューで、下のビューでマウスクリックすると、フォーカスを下に移したい場合です。
class TextMouseListener(view:TextView) extends MouseInputAdapter { override def mouseReleased(e:MouseEvent) { println(e.getPoint) if (e.isPopupTrigger) showPopup(e) else if (e.getButton == MouseEvent.BUTTON1) { view.pos2 = view.model.getNearPos(e.getPoint) } // クリックしたビューをフォーカス val textTab = SwingUtil.findRootContainer(view, classOf[TextTab]).asInstanceOf[TextTab] textTab.focusView = view // ビューにフォーカスを移す > view.grabFocus() view.frame.updateFrame() println("pos1="+view.pos1+" pos2="+view.pos2) } }