- PR -

JScrollPane使用上の留意点についておしえてください。

投稿者投稿内容
バンブー
会議室デビュー日: 2003/09/22
投稿数: 12
投稿日時: 2003-09-22 07:26
この2週間解決できずに困っています。
再現性はないのですが、JPanel上に貼り付けた複数個のJPanelのうち、あるひとつの
JPanelからアローキー入力を拾って、スクロールは固定したままフォーカスの移動だけさせたいのですが、コンテナのJPanelまでスクロールしてしまいます。
おそらく、requestfocusの仕様上の欠点かなにかのせいかと思われます。
JPanelにrequestfocusした直後にフォーカスがコンテナにもどってしまうなどということがあるのでしょうか?。あるいは、JScrollPane上のコンテナはつねにキー入力をひろっているのでしょうか?はたまた、Look&FeelでWindowsをデフォルトに設定している事自体がまちがいなのでしょうか?
このような状況に出くわした方でないとなかなか答えづらい質問かと思われます。
気長に待ちますので、どなたか助けてください。
_________________
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-09-22 11:42
unibon です。こんにちわ。

引用:

バンブーさんの書き込み (2003-09-22 07:26) より:
JPanelにrequestfocusした直後にフォーカスがコンテナにもどってしまうなどということがあるのでしょうか?。あるいは、JScrollPane上のコンテナはつねにキー入力をひろっているのでしょうか?はたまた、Look&FeelでWindowsをデフォルトに設定している事自体がまちがいなのでしょうか?


ちょっと良く分からなかったのですが「コンテナ」とはなにでしょうか。
コード:
JPanel panelA = new JPanel();
JPanel panelB = new JPanel();
JScrollPane scrollPane = new JScrollPane(panelB);
panelA.add(scrollPane);


での panelA のことでしょうか。
すなわち JScrollPane でもないのにスクロールするということでしょうか。

ちなみに JScrollPane は、フォーカスを持っていれば、
アローキー(上下)や Home/End/Page Up/Page Down キー や、
あるいはそれらと Ctrl キーの組み合わせでスクロールするという仕様だと思いますが、
それ自体を問題とされているのではないですよね?

あまり具体的な回答ではないのですが、まずは、
スクロールすることが問題なのか、フォーカスが獲得できているかどうかが問題なのかを、
切り分けてはどうでしょうか。
バンブー
会議室デビュー日: 2003/09/22
投稿数: 12
投稿日時: 2003-09-28 06:42
早速レスいただいたのに書き込みが遅れて申し訳ありません。
体調をくずして入院していました。新参ものにレスはそうこないものだと
思い込んでいただけに、早速のレス、本当にありがとうございます。
ところで、その後、いろいろ調べてみましたが、やっぱり解決できずにいます。
そこで、javaチュートリアルを精査してみたところおもしろいことを発見しました。
Scrolldemo.javaではアローキーによるスクロールが可能なのに、Scrolldemo2.javaでは
アローキーでスクロールできないのです。
コードを読み比べても自分の能力では決定的な差異は見つけられません。
ただ、ScrollDemo.javaのこーなーコンポーネントをaddする部分のコメントにbugという
一文字がありました。
ちなみにこの部分をコメントアウトして実行すると、上下キーは通常どおり機能するのに、左右キーが上下キーに入れ替わってしまうという現象が発生しました。
もうどうしてよいかさっぱりわかりません。

_________________
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2003-09-29 18:03
引用:

Scrolldemo.javaではアローキーによるスクロールが可能なのに、Scrolldemo2.javaでは
アローキーでスクロールできないのです。
コードを読み比べても自分の能力では決定的な差異は見つけられません。
ただ、ScrollDemo.javaのこーなーコンポーネントをaddする部分のコメントにbugという
一文字がありました。
ちなみにこの部分をコメントアウトして実行すると、上下キーは通常どおり機能するのに、左右キーが上下キーに入れ替わってしまうという現象が発生しました。
もうどうしてよいかさっぱりわかりません。



ただソースコードを眺めていただけでは、内容を理解するのは難しいでしょう。
開発環境が書かれていないようですが、おそらく何らかの統合開発環境を使用していることでしょう。これらのツールにはデバッガがついているはずなので、デバッガで処理を追いかけてみると、より理解を深めることが出来ると思います。
ピラルク
会議室デビュー日: 2003/06/06
投稿数: 4
投稿日時: 2003-09-30 23:32
こんにちは、ピラルクです。

JDKのVersionは何でしょうか?
SwingのFocusまわりは、JDKのVersionによって結構Bugが
含まれたりはずされたりして動きが違います。

現象が最初の質問では不明なので、最小限なソースを作って
提示されたらいかがでしょうか?(解決を少しでも望むのであれば)
それと、最新Versionでコンパイル&動作して、やはり再現するかも
検証されてみては。
バンブー
会議室デビュー日: 2003/09/22
投稿数: 12
投稿日時: 2003-10-02 04:08
大変貴重なご意見をいろいろ下さって本当に感謝しています。
この雰囲気だと本当に解決できるかも知れないと、期待をこめて、具体的に環境とコードを示したいと思います。
IDE:forte4 CommunityVersion
JDK:1.4.0 
OS:WindowsXP HomeEdition
-------- Code Sample ------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class ScrollDemo extends JPanel {

public ScrollDemo() {

JPanel buttonCorner = new JPanel();

JLabel picture = new JLabel();
picture.setPreferredSize(new Dimension(320,480));
picture.setText("This is Test of Scroll");

JScrollPane pictureScrollPane = new JScrollPane(picture);
pictureScrollPane.setPreferredSize(new Dimension(300, 250));

/******** No1 from *******/

JToggleButton isMetric = new JToggleButton("", true);
buttonCorner.add(isMetric);
pictureScrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER,buttonCorner);

/********* No1 to *****/

add(pictureScrollPane);

/********** No2 from *********/
FocusListener FListener[] =
         pictureScrollPane.getVerticalScrollBar().getFocusListeners();
pictureScrollPane.getVerticalScrollBar()
                     .removeFocusListener(FListener[0]);
/********** No2 to ***********/
}

public static void main(String[] args) {

JFrame.setDefaultLookAndFeelDecorated(true);

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JComponent newContentPane = new ScrollDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);

frame.pack();
frame.setVisible(true);
}
}
上記のコードはjavaチュートリアルにあるScrollDemo.javaを参考に余計な部分をどんどん削ってシンプルに書き直したものです。

問題点その1、No1,fromからNo1,to の部分は原典には存在するルーラーが直交する部分の部品のなごりですがこの部分をコメントアウトすると上下左右のバーを上下左右のアローキーで制御できなくなる。

問題点その2、No2.fromからno2.toの部分は、アローキーによる制御をはずしたくて、挿入したものだが、機能してくれない。コードがまちがっているのか?仕様として受け付けてくれないのか?

以上です。よろしくお願いします。



unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-10-02 12:48
unibon です。こんにちわ。

引用:

バンブーさんの書き込み (2003-09-28 06:42) より:
ちなみにこの部分をコメントアウトして実行すると、上下キーは通常どおり機能するのに、左右キーが上下キーに入れ替わってしまうという現象が発生しました。


この点に関してのみ書きますが、
フォーカスを獲得できるコンポーネントとしては、
縦・横それぞれのスクロールバーもあるようです。
たとえば Tab キーでフォーカスを切り替えることができ、
縦・横のいずれかのスクロールがフォーカスを持っている時は、
スクロールバーに対するキー入力になるようです。
この場合は、「上下」と「左右」のどれを押しても同じような挙動になって見えます
(1次元のスクロールバーに対する値の増減になるため)。
ピラルク
会議室デビュー日: 2003/06/06
投稿数: 4
投稿日時: 2003-10-02 17:50
こんにちは、ピラルクです。

現象を分析してみると、
・垂直スクロールバー・水平スクロールバー、コーナーのJToggleButton
 の3つでフォーカスを回している。
・垂直or水平スクロールバーがFocusを持つと、矢印キーが上下であろう
 が左右であろうが、おかまいなしに、そのFocusを持つスクロールバー
 が動く。
・コーナーのJToggleButton(というより、おそらく、自身では矢印キーを
 処理しないComponent全て)がFocusを持つと、上下は垂直に、左右は水平
 のスクロールバーが動く。
ではないでしょうか。

上記のことは、

コード:
  public static void main(String[] args) { 
    ……
    final JFrame frame = new JFrame(); 
    ……
    new Thread() {
      public void run () {
        for (; {
          Component comp = frame.getFocusOwner(); 
          frame.setTitle(comp == null ? "null": comp.toString());
          //sleepも入れたほうがベター
        }
      }
    }.start();
    ……



というように常にどこにFocusがあるのかを追跡するコードを
一時的に入れたりすると検証に役立ちます。


で、どういう挙動を望んでいるのか、いまひとつ私もわかってない
のですが

まず上下でも左右でおかまいなしに1つのスクロールバーが動いて
しまうという、直感的ではないこの動作をやめさせたいのなら、

pictureScrollPane.getHorizontalScrollBar().setFocusable(false);
pictureScrollPane.getVerticalScrollBar().setFocusable(false);

を追加するのが良いでしょう。

さらに、矢印キーでスクロールしてしまうのをとめたいなら、

コード:
  JScrollPane pictureScrollPane = new JScrollPane(picture) {
    protected boolean processKeyBinding(KeyStroke ks,
              KeyEvent e, int condition, boolean pressed) {
      return false;
    }
  }; 



という手法があります。上記はおもいっきり、はしょった書き方
なので、実際は不要なキーを除いて、superを呼ぶように書く方が
良いでしょうし、必要ならちゃんと名前を付けてサブクラスを定義
するなりしてください。

また、「フォーカスがコンテナにもどってしまう」とか最初にあり
ますが、通常PanelなどはFocusをもてません。
持たせたい場合は、setFocusable() で設定します。しかし画面上の
全てのComponent()がEnabled(false)されたりしてどこにもFocusの
行き場がなくなった場合は、Focusable(false)な所へ行ったりもし
ます。Focusの挙動の検証には、最初にそういうクセを押さえておか
ないと、検証を重ねて逆にますます理解不能に陥ったりするので、
慣れないうちは、最もシンプルな画面から1つずつComponentを追加
して、あらゆるキー押下パターンを順に試していくぐらいの根気が
時として必要です。

それとデフォルトのリスナーをはずす処理を試みておられますが、
このようなアプローチはリスキーで好ましくないと思います。
将来のVersionで弊害が表面化する可能性がありますし、気づいて
いない弊害が現Versionで既に発生しているかもしれません。
(何が入っているのかswingのsourceを追ってみたが挫折した...)
process〜系で処理をかます方がまだマシでしょう。この場合も
必要最小限な処理だけ入れて、極力superを呼ぶように心がける
ことです。標準の動作を変える処理の追加は、全て爆弾の埋め込み
と考えるぐらいでないとswingは手に負えなくなります。

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