- PR -

JInternalFrameではKeyListenerのイベントが発生しない?

1
投稿者投稿内容
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-03-17 14:28
こんにちは。いつもお世話になっています。

今、JDesktopPaneとJInternalFrameで、MDI(マルチドキュメントインターフェース)
のフォームを作っています。

が、子フォーム(JInternalFrame)に KeyListener でキーイベントを実装しているの
ですが、なぜかイベントが子フォームでは発生しません。
マウスイベントなどは正常に発生します。何かご存知の方はおられませんか?

参考にサンプルを添付します。
※サンプルは、参考のために親フォームもキーイベントを実装しています。始めは正常に
キーイベントが発生しているのですが、子フォームがアクティブになった以降、イベント
はなぜか発生しなくなります。

<環境>
OS:Windows2000
JDK:1.4.1_01

<ソース>
import javax.swing.*;
import java.applet.*;
import java.awt.event.*;
import java.awt.*;

class KeyTest extends JFrame implements KeyListener{
private JDesktopPane desktop;
public KeyTest(){
Container cont = getContentPane();
desktop = new JDesktopPane();
cont.add( desktop, BorderLayout.CENTER);
SubFrame sub = new SubFrame();
sub.setSize(200,200);
sub.setVisible(true);
desktop.add(sub);
addKeyListener(this);
}

public void keyPressed(KeyEvent e){
System.out.println("keyPressed:"+e.getKeyCode());
}
public void keyReleased(KeyEvent e){
System.out.println("keyReleased:"+e.getKeyCode());
}
public void keyTyped(KeyEvent e){
System.out.println("keyReleased:"+e.getKeyCode());
}
public static void main(String[] args){
KeyTest frm = new KeyTest();
frm.setSize(400,400);
frm.setVisible(true);
}
}

class SubFrame extends JInternalFrame implements KeyListener,MouseListener {

public SubFrame(){
super("てすと");
addKeyListener(this);
addMouseListener(this);
}
public void keyPressed(KeyEvent e){
System.out.println("sub keyPressed:"+e.getKeyCode());
}
public void keyReleased(KeyEvent e){
System.out.println("sub keyReleased:"+e.getKeyCode());
}
public void keyTyped(KeyEvent e){
System.out.println("sub keyReleased:"+e.getKeyCode());
}
public void mouseClicked(MouseEvent e){
System.out.println("sub mouseClicked:");
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
}




[ メッセージ編集済み 編集者: maru 編集日時 2003-03-17 14:45 ]
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-03-17 14:56
unibon です。こんにちわ。

引用:

maruさんの書き込み (2003-03-17 14:28) より:
<環境>
OS:Windows2000
JDK:1.4.1_01


マウスはフォーカスに依存しませんが、キーはフォーカスに依存し、
フォーカスまわりは JDK 1.3 と 1.4 で仕様が多少違うため、
フォーカスまわりの問題だと思います。
この推測が正しいか別にして、提示されたコードを 1.3.1 と 1.4.1 で動かすと
確かに挙動は異なります。
1.3.1 で動かすとおそらく目論まれた挙動になると思います。
対処方法はすぐに思い出せないのですが、
Bug Parade でいくつかヒットしたかもしれません。

#以下、あとで追加しました。

http://search.java.sun.com/search/java/index.jsp?qt=%2B+%2BKeyListener+Focus+JInternalFrame&col=javabugs&category=&state=&query=KeyListener+Focus+JInternalFrame
あたりでヒットする上位のものがこれに該当するようです。
あまり見ていませんが、
http://developer.java.sun.com/developer/bugParade/bugs/4647551.html
が近いような気がします。
#仕様ではなくバグ?

[ メッセージ編集済み 編集者: unibon 編集日時 2003-03-17 15:17 ]
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-03-17 15:25
こんにちは。

>マウスはフォーカスに依存しませんが、キーはフォーカスに依存し、
>フォーカスまわりは JDK 1.3 と 1.4 で仕様が多少違うため、
>フォーカスまわりの問題だと思います。
ある本に、KeyEventが発生しないJLabelにKeyEventを無理やり実装するやり方がのって
いました。内容は、ラベルは isFocusTraversable()メソッドの戻り値が false なので
フォーカスを得られないのでキーイベントが発生しない。そこで、isFocusTraversable()
をオーバライドしてtrueを返すようにするという内容でした。

まさかと思い、JInternalFrameのisFocusTraversable()(JDK1.4からはisFocusable())
を確認したところ結果は true でした。まさかね。

やっぱりバグなのかなぁ?結構、初歩的な使い方だと思うのですが、こんなものでバグがある
となると、困りましたなぁ。
ESCキーのキャンセル機能やファンクションキーをどうしようかなぁ・・・???

http://developer.java.sun.com/developer/bugParade/bugs/4647551.html
を読みました。(というか、英語わかんないんでExciteで翻訳)
これでしょうね。・・・う〜ん。どうしよう。


[ メッセージ編集済み 編集者: maru 編集日時 2003-03-17 15:29 ]

[ メッセージ編集済み 編集者: maru 編集日時 2003-03-17 16:58 ]
うのきち
ベテラン
会議室デビュー日: 2003/02/17
投稿数: 55
投稿日時: 2003-03-18 00:30
JInternalFrameの上には、何も貼っていないんですか?
もしもフォーカスを受け取れるコンポーネントを貼っているなら、それにKeyListenerを登録すると、イベントが取れるようです。
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-03-18 09:49
おはようございます。
>もしもフォーカスを受け取れるコンポーネントを貼っているなら、それにKeyListener
>を登録すると、イベントが取れるようです。
なるほど!すごく単純なことですが思いつきませんでした。

イベントを実装したい JInternalFrame にはスクロールペインとカスタマイズしたラベルを
貼り付けて、画像プレビューみたいに作っているのですが、どちらもおそらくイベントを取れ
ないでしょうけど、ちょうど前述のようにラベルにイベントを発生させる方法があるので、
それでやってみます。

ありがとうございました。
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2003-03-18 14:40
こんにちは。

上記のようにラベルをカスタマイズして、イベントを発生させるようにはできたのですが、
あやまってTABキーを押すとフォーカスがどっかへいってしまうようで、イベントが発生
しなくなります。数回TABを押すとフォーカスが戻ってきた時点で、再度イベントが発生
するようになります。
う〜ん。どうしよう。


[ メッセージ編集済み 編集者: maru 編集日時 2003-03-18 14:41 ]
うのきち
ベテラン
会議室デビュー日: 2003/02/17
投稿数: 55
投稿日時: 2003-03-18 18:20
1.4なら、FocusTraversalPolicyで、特定のコンポーネントだけにしかフォーカスを移動出来ないようにできそうです。試してみたことはないですが...
Okayu3
会議室デビュー日: 2004/03/11
投稿数: 11
投稿日時: 2004-03-11 15:41
任意のキーイベントを拾いたい、ということではなく、
特定のキーだけでいいのなら 方法があります。

必要な キーイベントを InputMapに設定して、

対応する ActionMapのなかで、
該当するInternalFrameが activeFrameなら
そのInternalFrameに対して キーイベントがあったと判断し、
処理を行う Action を 設定する という方法があります。

無理やり Focusイベントを拾うよりは穏当かもしれませんね。

#"F1"キー でヘルプ、なんていう状況では この手を使っています。
1

スキルアップ/キャリアアップ(JOB@IT)