この人頭いいなと思ったエピソード

こんにちは、tomokooです。

JDK1.2では、JFrameにJTextやJButtonを配置した場合、setNextFocusableComponentでフォーカスを制御してました。
SUNのJavadocによるとJDK1.4では、"推奨されていません。 JDK バージョン 1.4 以降は、FocusTraversalPolicy に置き換えられました。 "
とあります。
FocusTraversalPolicyを見たりしたのですが、いまいちどう使っていいかよくわかりません。
移行の具体的な例を教えてほしいのですが。。。
例が載ってるURLや本でもかまいません。

よろしくお願いします。

A 回答 (4件)

4回目の書き込みです。

(^^;
ちょっと長いんですが、サンプル作成してみました。
従来のように、Nextを設定して使うようなFocusTraversalPolicyです。
Shift+TABによる逆順遷移については未対応で、デフォルトの動作をします。

ソースは見やすいように、半角スペース2個で全角スペースにしてあるので、
コピーしたあとに置換してください。

import java.awt.*;
import java.awt.event.*;
import java.util.Hashtable;

public class FocusTest extends Frame{
  public static void main(String args[]){
    new FocusTest().show();
  }
  public FocusTest(){
    Button btn1 = new Button("Button 1");
    Button btn2 = new Button("Button 2");
    Button btn3 = new Button("Button 3");
    Button btn4 = new Button("Button 4");
    Button btn5 = new Button("Button 5");
    setSize(200, 200);
    setLayout(new BorderLayout());
    add(btn1, BorderLayout.NORTH);
    add(btn2, BorderLayout.WEST);
    add(btn3, BorderLayout.CENTER);
    add(btn4, BorderLayout.EAST);
    add(btn5, BorderLayout.SOUTH);
    btn4.setEnabled(false);
    addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
        System.exit(0);
      }
    });
    //フォーカス遷移ポリシーの作成
    FocusTestTraversalPolisy tp = new FocusTestTraversalPolisy();
    //遷移順の設定
    tp.setNextFocusableComponent(btn1, btn5);  //Button1→Button5
    tp.setNextFocusableComponent(btn5, btn2);  //Button5→Button2
    tp.setNextFocusableComponent(btn2, btn4);  //Button2→Button4
    tp.setNextFocusableComponent(btn4, btn3);  //Button4→Button3
    tp.setNextFocusableComponent(btn3, btn1);  //Button3→Button1
    //このFrameのフォーカス遷移ポリシーとして設定
    setFocusTraversalPolicy(tp);
  }

  private class FocusTestTraversalPolisy extends ContainerOrderFocusTraversalPolicy
  {
    private Hashtable focusMap;
    private FocusTestTraversalPolisy(){
      focusMap = new Hashtable();
    }
    public void setNextFocusableComponent(Component src, Component dest){
      focusMap.put(src, dest);
    }
    public Component getComponentAfter(Container focusCycleRoot, Component aComponent){
      //Hashtableから次のコンポーネントを取得
      Component next = (Component)focusMap.get(aComponent);
      if(next == null){
        //nullだったらデフォルトの動作
        return super.getComponentAfter(focusCycleRoot, aComponent);
      }
      if(!accept(next)){
        //遷移不可の場合は、さらにその次。(再帰)
        return getComponentAfter(focusCycleRoot, next);
      }
      return next;
    }
  }
}

この回答への補足

sasadoraさん、4回もお付き合いいただきありがとうございました。
また問題発生したらここで質問しますので、そのときはよろしくお願いします!
まだtab1回で遷移してくれませんが、とりあえずここで締め切ります。
はー、sasadoraさんのメアドが知りたい・・・。

ありがとうございました♪

補足日時:2002/07/30 14:49
    • good
    • 0
この回答へのお礼

sasadoraさん、大助かりです!
ありがとうございますぅ(T_T)
ちゃんと順番どおり動きました。
しかしここでまた問題が。。。
tabを2回押さないと動かない。
なんでだ!?
JButtonやJComboBoxもカスタマイズしちゃってるからなんか影響出てるのかなー?
ちょっと調べてみます。
ありがとうございました!!

お礼日時:2002/07/30 13:15

JDK1.4.0入れました。

(^^;
ためし中です…。

>コンテナにaddした順にフォーカスを遷移させたいんです。でもaddした通りに動いてくれないんです(TT)

addした順というのは不適切でした。
コンテナ内部におけるインデックスの順です。
インデックスを指定してaddすると、addするのが後でも指定した位置にaddできます。
FlowLayoutの場合、インデックス順序と配置順序が一致すると思うんですが、
BorderLayoutの場合、addした順に遷移すると思います。
Layoutは何を使用していますか?

>そしてsasadoraさんが教えてくださった方法っていうのは、
>画面ごとにフォーカス遷移クラスを作るってことなのでしょうか?

それは設計次第だと思います。40画面すべてで共通のFocusTraversalPolicyを作ることも可能です。
問題はどうやってAfter,BeforeのComponentを判断するかであって、それを40画面すべてで共通的な判断ロジックで作れば1つのFocusTraversalPolicyで十分かと思います。

FocusTraversalPolicyを使用するのも一案ですが、tomokooさんの場合は、
Layoutを別のものに変えれば十分な気もします。

とりあえず今、試してみているので、
あとでサンプルを書き込みにきますね。
(私にとっても非常に勉強になります。)
    • good
    • 0

ためしてもいないので恐縮なんですか…。


やりたいこととしては、デフォルトではなく独自のフォーカス遷移を定義したいんですよね?

方法としては、
1.FocusTraversalPolicyを継承したサブクラス作成する。
 このサブクラスに独自のフォーカス遷移ロジックを定義すればいいんだと思います。
2.作成したクラスを、指定のコンテナにsetFocusTraversalPolicyで指定する
 独自のフォーカス遷移ロジックがそのコンテナに対して適用されるんだと思います。

こう思ってます。


ただし、FocusTraversalPolicyを継承してゼロから作成するのは大変なので、標準のFocusTraversalPolicyサブクラスである、ContainerOrderFocusTraversalPolicyを継承して作ったほうがらくだと思います。

ContainerOrderFocusTraversalPolicyを継承して、getComponentAfterなどをオーバーライドしてやればいいんじゃないかと。(デフォルトの動作のままでよいときは、オーバーライドしないでおく。)

単純に、コンテナに追加した順序と異なる順序で遷移したい。などという簡単な場合は、コンテナに追加する順序をフォーカス遷移と同じ順序にしたほうが、いいような気もします。(addする順序を変える)

#1.4は使ってないんで試せないんですが、いい機会なので暇があったら
#私も試してみようかと思います。
    • good
    • 0
この回答へのお礼

sasadoraさん、二回もありがとうございます!

コンテナにaddした順にフォーカスを遷移させたいんです。でもaddした通りに動いてくれないんです(TT)
画面を左から右へフォーカスが動いちゃうんです。
なにかを設定しないとだめなのでしょうか?
そしてsasadoraさんが教えてくださった方法っていうのは、画面ごとにフォーカス遷移クラスを作るってことなのでしょうか?
画面は40ほどあるのでそれはとても大変な気が・・・。
もっともそれしかないならやるしかありませんが。
回答にあげてもらったクラスを覗きつつ、さらに色々試してみます。
ありがとうございました!

お礼日時:2002/07/29 18:22

こんにちは、tomokooさん。



私も使ったことないので、よく分からないのですが…。
こんなページがありました。
参考になるんではないでしょうか?

参考URL:http://www-6.ibm.com/jp/developerworks/java/0203 …
    • good
    • 0
この回答へのお礼

sasadoraさん、お早いお返事、ありがとうございます!

実はこれ、見たんです。
で、"リスト1. 理論的なフォーカス管理の例"のとおりやったのに動かない。。。
なんでだー?
設定が悪いのか、記述が抜けてるのか、私の頭が悪いのか(←これは否定できない・・・)
使ったことないのにお返事いただいて、ホントありがとうございました。
ちょっと感動しました(T_T)

お礼日時:2002/07/29 16:47

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!