0

のサブクラスであるJScrollPane表示(ビューポートビューとして)があります。MyPanelJPanel

MyPanelをオーバーロードしてカスタム ペインティングを実装しますpaintComponent。の表示可能なコンテンツの合計サイズは一般に非常に広く (ビューポートMyPanelのサイズよりも 50 倍から 200 倍広いことを意味します)、 を使用して水平方向にスクロールし、下にある のさまざまなセクションを表示します。スクロール バーのつまみを使用して、 の特定の領域を手動でシークすることもできます。JScrollPaneTimerMyPanelMyPanel

私の実装では、現在、 を使用してビュー ポートに現在表示されているpaintComponent部分を見つけており、ビュー ポートの位置が変更されるたびにその部分をペイントしています。MyPanelJViewport#getVisibleRect

MyPanelこれは問題なく動作しますが、時間指定されたスクロールでは一度にビューポート幅の 1/50 しか移動しないため、表示部分のかなりの割合を何度も再描画することになります。また、通常は の水平範囲全体をスクロールすることMyPanelになるため、少なくとも 1 回はすべてをペイントする必要があります。

MyPanelそのため、 の内容全体を1 回だけ (? に)BufferedImageペイントしてから、.JScrollPaneJViewportBufferedImage

直感的に、これはこれを処理する最も効率的な方法であり、比較的一般的な方法であるように思えます。

Swing のチュートリアルやその他の情報源を調べていると、Swing はすでにダブル バッファリングされていることがわかりました。Swing の機能とは関係なく、自分の力でこれを強制しようとすると、トリプルバッファリングになってしまうようです。

これを行うために悪用するレシピ(存在する場合)が見つかりJScrollPaneませんでした。

利用可能な例、またはこれを行う方法についての指示はありますか (可能な場合)?

4

1 に答える 1

0

Swing は、コンポーネントの必要最小限の領域のみを自動的にペイントします。repaint(4 args)コンポーネントが部分的に変更され、可視領域全体を再描画したくない場合にのみ役立ちます。そして、あなたの実践では、 と同じ効果がありrepaint(no-args)ます。

質問で説明したように、自動クリップ領域はすでに可視性の問題に対して十分に小さいです。また、プログラムで構成できます。

また、スクロールについて心配する必要はありません。JScrollPane は、その子の再描画を自動的に呼び出します。

これらを簡単に試すことができます:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Test extends JFrame {

    private Random rnd = new Random();
    private Color c = Color.WHITE;

    public Test () {
        final JPanel pnl = new JPanel() {

            @Override
            public void paintComponent (Graphics g) {
                super.paintComponent(g);
                g.setColor(c);
                g.fillRect(0, 0, getWidth(), getHeight());
                Rectangle r = g.getClipBounds();
                System.out.println(r.width + ", " + r.height);
            }
        };
        pnl.setPreferredSize(new Dimension(10000, 10000));

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400, 400);
        setLocationRelativeTo(null);

        add(new JScrollPane(pnl));

        setVisible(true);

        new Thread() {

            @Override
            public void run () {
                while (true) {
                    c = new Color(rnd.nextInt(0xffffff));
                    pnl.repaint();
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {}
                }
            }
        }.start();
    }

    public static void main (String args[]) {
        new Test();
    }
}
于 2013-01-24T02:55:39.570 に答える