質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

1347閲覧

processKeyEventとaddkeylistenerの違い

algobeginner

総合スコア16

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2017/11/11 22:28

編集2017/11/13 06:35

Swingの勉強をしていてprocessKeyEventとaddkeylistenerを簡単にですが試してみました。使ってみた感想としてprocessKeyEventの方がenableEventsで簡単にキーイベントを受け付ける用に出来て楽に感じました。addkeylistenerの方はインターフェースの継承の関係で使わないイベントであってもメソッドを書かなければならず若干ソースが多くなってしまい今のところaddkeylistenerのメリットがわかりません。しかし便利なメソッドには何か落とし穴がある事が多い気がします。なのでこの二つのメソッドの違いについてご教授いただければ幸いです。

追記

回答ありがとうございます。回答に書かれてる事を理解するために入力したキーを真ん中のJLabelに表示するソースを書いて順番に実行してみました。

  • 1.まず①の番号が付いたメソッドを試し、キーリスナーをJFrameに加えた後コンパイルして実行。

結果
JFrameにフォーカスが当たらないのか中央の文字が変更されない。

  • 2.次に左側のJbuttonにキーリスナーを追加して試してみる。

結果
左側のJButtonをクリックしてフォーカスが当たってる状態のみ文字が変わった。

  • 3.次に②のメソッドを試し、enableEventでキーイベントを有効にしたJButtonクラスをJPanelの左側にはめ込む

結果
先ほどと同じ結果

これらを踏まえてprocessKeyEventとaddkeylistenerを比較してみるとprocessKeyEventの場合キー入力を受け付ける部品を作るときenableEventsのアクセス修飾子の問題で部品を継承したクラスを作らなければならないのが大変に感じました。また、addkeylistenerの場合キー入力を受け付けたいコンポーネントにそのメソッドを書くだけで良く、キーリスナーも使い回しが効くので便利に感じました。回答者様の伝えたいこととズレてる気がしますが確かにaddkeylistenerのメリットを体感する事が出来たと思います。

import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JLabel; import javax.swing.JButton; import java.awt.Dimension; import java.awt.Color; import java.awt.Font; import java.awt.BorderLayout; import java.awt.event.KeyEvent; import java.awt.event.KeyAdapter; class FocusCheck extends JFrame { public static void main( String[] args ) { FocusCheck fc = new FocusCheck(); fc.setVisible( true ); } //文字を表示するJLabelを入れる private static JLabel centerJLabel; FocusCheck() { //JFrameの基本設定 super( "テスト" ); setSize( 600, 450 ); setLocationRelativeTo( null ); setDefaultCloseOperation( EXIT_ON_CLOSE ); ① addKeyListener( new KeyListenerToJFrame() ); ② enableEvents( java.awt.AWTEvent.KEY_EVENT_MASK ); //JPanelをJFrameに追加 JPanel jp = new JPanel( new BorderLayout() ); getContentPane().add( jp ); //左側のボタンをJPanelに追加 ① jp.add( new JButtonTest(), BorderLayout.WEST ); ② jp.add( putLeftJButton(), BorderLayout.EAST ); //右側のボタンをJPanelに追加 jp.add( putRightJButton(), BorderLayout.EAST ); //文字を表示するJLabelをJPanelに追加 centerJLabel = putJLabel(); jp.add( centerJLabel, BorderLayout.CENTER ); } //左側のJButtonを作成しそのインスタンスを返すメソッド public JButton putLeftJButton() { JButton jb = new JButton( "左ボタン" ); jb.setPreferredSize( new Dimension( 100, 75 ) );     //①の状態に更に次のメソッドを追加 ① jb.addKeyListener( new KeyListenerToJFrame() ); return jb; } //右側のJButtonを作成しそのインスタンスを返すメソッド public JButton putRightJButton() { JButton jb = new JButton( "右ボタン" ); jb.setPreferredSize( new Dimension( 100, 75 ) ); return jb; } //中央の文字を表示するJLabelを作成しそのインスタンスを返すメソッド public JLabel putJLabel() { JLabel jl = new JLabel( "文字を入力してください" ); Font f = new Font( Font.DIALOG_INPUT, Font.BOLD, 30 ); jl.setFont( f ); jl.setHorizontalAlignment( JLabel.CENTER ); return jl; } //JFrame用のキーリスナークラス class KeyListenerToJFrame extends KeyAdapter { KeyListenerToJFrame(){ System.out.println( "JFrame用のキーリスナークラスがインスタンスされました"); } public void keyPressed( KeyEvent e ) { System.out.println( "JFrameでキーを入力しました" ); centerJLabel.setText( String.valueOf( e.getKeyChar() ) ); } } //キー入力時に実行されるメソッド protected void processKeyEvent( KeyEvent e ){ System.out.println( "キーを入力しました" ); centerJLabel.setText( String.valueOf( e.getKeyChar() ) ); } //JButtonを継承しenableEventsでキーイベントの送信を有効にしたクラス class JButtonTest extends JButton { JButtonTest(){ super( "左ボタン" ); enableEvents( java.awt.AWTEvent.KEY_EVENT_MASK ); } protected void processKeyEvent( KeyEvent e ){ System.out.println( "JButtonTestでキーを入力しました" ); centerJLabel.setText( String.valueOf( e.getKeyChar() ) ); } } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

汎用性という意味からいえばaddKeyListenerを用いるのが普通です。

JFrameで全てのキーイベントをハンドリングするような単純なゲーム画面のようなものだと確かにprocessKeyEventをオーバーライドするのは便利に感じると思います。しかしJButton, JTextFieldなどのキーイベントにより制御されるような部品を使い始めるともはやJFrame#processKeyEventには(そのままでは)キーイベントが配送されなくなります。これは本来キー入力はフォーカスがあるコンポーネントへイベント配送されるメカニズムになっているためです。processKeyEventを単純にオーバーライドしただけではフォーカスに対応した処理方式とはいえないのですね。

一方、addKeyListnerを用いてキーイベントハンドラーを登録するやりかたは(適切にフォーカス制御をするという条件の下では)ハンドラーが行うべき仕事が単純になります。それはフォーカスの状態によって今現在どのコンポーネントがキーイベントを受け取るべきかをswingの実装が面倒を見てくれ、KeyListenerの実装側は「今自分がキーイベントを受け取れる状態にある」という前提でキーの処理だけに集中できるからです。もしaddKeyListenerを使わずにprocessKeyEventをオーバーライドしてしまうと、フォーカスがあるコンポーネントに正しくイベントハンドリングを行わせるための配慮を自前でやらなければならず却って面倒なことになります。


なお、addKeyListenerを用いた場合、複数のハンドラーメソッドをオーバーライドしなくてはならず面倒なのはおっしゃるとおりですが、そのために便利なクラスKeyAdapterがあります。このクラスはKeyListenerの全てのメソッドが「何もしない」ようにオーバーライドされているクラスでして、それを用いて興味があるイベントのメソッドのみオーバーライドするような使い方をします。

java

1component.addKeyListener(new KeyAdapter() { 2 @Override 3 public keyPressed(KeyEvent ev) { 4 ... 5 } 6 // 他のメソッドを一々オーバーライドする必要がない 7});

このようなクラスは他にもあり、ComponentAdapterとかWindowAdapterなど、複数のハンドラーを持つXxxLisenterの実装の際に重宝します。

投稿2017/11/12 01:41

編集2017/11/12 01:42
KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

algobeginner

2017/11/13 06:36

回答欄に書くにはちょっと窮屈なので質問の追記に回答者様への返答を書きます。
KSwordOfHaste

2017/11/13 06:47 編集

追記された内容を拝見しました。質問者さんが述べておられる、「継承」による実装と別クラスのリスナーへイベントハンドリングを「移譲」する方式にも使い勝手の差があるという点、同感です。画面上にコンポーネントが増えてくるとこの違いが顕著になるように思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問