0

java.awt.ScrollPaneクラスのSCROLLBARS_AS_NEEDED表示ポリシー処理コンポーネントのサイズ変更に問題があります。理想的には、Scrollpaneよりも大幅に小さいコンポーネントを含むScrollPaneがあり、Scrollpaneを子コンポーネントよりもまだ大きいサイズに縮小すると、スクロールバーは表示されません。ただし、実際には、サイズ変更操作の実行中に両方のスクロールバーがちらつくように見え、操作が完了した後の次の再描画まで持続する場合もあります。これが私が何を意味するかを示すための小さな例です:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Tester implements Runnable{

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.setProperty("sun.awt.noerasebackground", "true");
        Tester t = new Tester();
        SwingUtilities.invokeLater(t);
    }

    @SuppressWarnings("serial")
    @Override
    public void run() {
        JFrame frame = new JFrame("Tooltip tester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 800);
        Canvas c = new Canvas(){
            @Override
            public void paint(Graphics g){
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
            }
        };
        c.setPreferredSize(new Dimension(400, 400));
        ScrollPane s = new ScrollPane();
        s.add(c);
        frame.add(s);
        frame.setVisible(true);
    }
}

上記のアプリケーションでウィンドウを縮小すると、スクロールバーが点滅します。これは、ScrollPaneのピアの実装のバグが原因であると思います。(ソースはこちら)エラーがあると思われるメソッドをコピーしました(リンクの145行目)。

Dimension getChildSize() {
   ScrollPane sp = (ScrollPane)target;
    if (sp.countComponents() > 0) {
        Component c = sp.getComponent(0);
        return c.size();
    } else {
        return new Dimension(0, 0);
    }
}

私には、getChildSize()メソッドはc.size()ではなくc.getPreferredSize()を呼び出す必要があるようです。ScrollPaneの子のサイズが現在の推奨サイズよりも大きい場合は、スクロールバーが表示されずに縮小できるはずです(私の意見では)。この理論をテストするために、上記の例のsize()メソッドをオーバーライドします。

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Tester implements Runnable{

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.setProperty("sun.awt.noerasebackground", "true");
        Tester t = new Tester();
        SwingUtilities.invokeLater(t);
    }

    @SuppressWarnings("serial")
    @Override
    public void run() {
        JFrame frame = new JFrame("Tooltip tester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 800);
        Canvas c = new Canvas(){
            private Dimension prefSize = new Dimension();
            @Override
            public void paint(Graphics g){
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
            }

            @Override
            public void setPreferredSize(Dimension preferredSize) {
                prefSize = preferredSize;
                super.setPreferredSize(preferredSize);
            }

            @Override
            public Dimension size() {
                return prefSize;
            }
        };
        c.setPreferredSize(new Dimension(400, 400));
        ScrollPane s = new ScrollPane();
        s.add(c);
        frame.add(s);
        frame.setVisible(true);
    }
}

このコードは、私が望むとおりに動作します。ただし、size()メソッドをオーバーライドして、ドキュメントに記載されている以外のことを行うことは、この問題を解決するための特に洗練された方法ではありません。私はここで何か間違ったことをしているに違いないように感じます。X11用のScrollPaneピアのかなり基本的な機能が壊れている可能性はありますか?

その他の関連する注意事項:
-java.awt.Canvasの使用は、私の目的では交渉できません。私の実際のアプリケーションでは、JavaAWTネイティブインターフェイスを使用して非常にすばやく何かを描画しています。
-Java7以降のバージョンのJava6でのライト/ヘビー級の互換性の新しい改善に関するドキュメントを読みましたが、どちらの場合も実際には改善が見られなかったため、swing.JScrollPaneではなくawt.ScrollPaneを使用することにしました。いずれにせよ、上記の単純なケースではScrollPaneが正しく機能するはずです。

4

1 に答える 1

1

将来の読者のために、SSCCEなしであなたを助けるのは難しい

ただし、実際には、サイズ変更操作の実行中に両方のスクロールバーがちらつくように見え、操作が完了した後、次の再描画まで持続することさえあります。

  • 使用された LCD/LED パネルはそれらのちらつきを引き起こしました (MsExcell など、何度も議論されています)。

  • 同じちらつきは、JScrollPane を使用した Swing JFrame の場合です

  • CRT またはプラズマ ディスプレイに表示されない

  • PC で FullHD ビデオを再生する場合、サイズ変更が終了するまで待機しているすべての優れたマルチメディア プレーヤーが終了した後、利用可能なスペースをコンテナーに入力します。


  • ComponentListener を追加する必要があります。Swing Timer を小さな遅延 (KMPlayer で 350 ~ 500 ミリ秒を表示) に配置し、サイズを変更して Timer#restart の呼び出しを続ける必要があります。

  • Canvas は CAD / CAM、OpenGL(CL) の優れた回避策であり、優れた Java ビデオ プレーヤーは AWT ベースです

  • Swing Container と AWT コンテンツの混合を避ける必要があり、すべてが AWT (装飾されていないコンテナー) に基づいています。

于 2012-06-26T18:44:04.253 に答える