2

次のコードがあるとします。

( を拡張するクラスでJPanel):

public void paintComponent(Graphics g) {
    g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null);
}

dx1dy1が負の場合、またはdx2dy2が の幅よりも大きいJPanel(つまり、画像の一部が画面外になる) 場合、drawImage()レンダリングされるものを調整して、 に表示されている部分のみに「注意を払う」ようにしJPanelますか? に非常に大きな画像を描画すると遅くなる可能性があるためJPanel、これについて興味があります。paintComponent()

4

1 に答える 1

3

ここには問題の 2 つの側面があります...

1.大きな画像の読み込み

コード例では、すでに大きなイメージがメモリにロードされています (コンポーネントに直接ペイントしています)。つまり、非常に大きな画像がある場合、最初に問題が発生するのは、それを描画するためにメモリにロードし始めるときです (方法は問題ではありません) 。完全にロードすると、大量のメモリが消費されます。

標準 Java には多くのツールが用意されていないため、大きな画像を扱う場合、これが主な頭痛の種になるはずです。基本ツールを使用して完全な画像のみをロードできます。

画像の一部を読み込む (常に可能かどうかはわかりません) か、大きな画像を部分に分割して表示された画像部分のみを読み込むいくつかの代替方法を検討することをお勧めします。JAI のようなサードパーティのライブラリが役立つかもしれません。

とにかく、それはすべて「歌詞」です-あなたが尋ねた2番目の問題に行きましょう.

2. コンポーネントに大きな画像をペイントする

Swing のチュートリアルをいくつか読んだことがある方は、このクリップをご存知かもしれません。また、通常はコンポーネントの現在の可視境界に設定されていることも知っているかもしれません。はい、見える部分だけです。

したがって、5000x5000 px のサイズのパネルに 5000x5000 px の画像がペイントされているようなものがあるが、パネルの表示部分が 500x500 px しかない場合、画像も下にあるグラフィックスによってクリップされ、クリップに収まる部分のみが表示されます。描きました。

この最適化は、さまざまな形状のペイント/塗りつぶしや、グラフィックを使用したその他の操作にも機能します。明らかなことではありませんが、ほとんどの場合、完全な形状/イメージをペイントし、下にあるグラフィックスでペイント操作を最適化する方が適切です。ほとんどの場合、形状/画像を手動でクリップして結果をペイントするよりも数倍速くなります。

もう1つ-グラフィックスに画像を描画することは、Graphics2Dで最も高速な操作の1つであるため、あまり焦点を当てません。

Graphics2D 内部実装によって提供される描画の最適化を明確に示すこの小さな例を確認できます。

public class ImageDrawTest
{
    public static void main ( String[] args )
    {    
        final ImageIcon icon = new ImageIcon ( "C:\\large.jpg" );

        JComponent c = new JComponent ()
        {
            protected void paintComponent ( Graphics g )
            {
                super.paintComponent ( g );

                long time = System.nanoTime ();
                g.drawImage ( icon.getImage (), 0, 0, null );
                time = System.nanoTime () - time;
                System.out.println ( time );
            }
        };

        JFrame f = new JFrame ();
        f.getContentPane ().setLayout ( new BorderLayout () );
        f.getContentPane ().add ( c );
        f.setSize ( 200, 100 );
        f.setLocationRelativeTo ( null );
        f.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        f.setVisible ( true );
    }
}

C:\\large.jpg利用可能な大きな画像パスを使用する代わりに。

この例を実行してフレームのサイズを変更し、コンポーネントの表示領域を変更して出力を確認します。再描画ごとにナノ秒単位で描画時間が表示されます。表示領域のサイズによって大きく異なります。

于 2013-05-14T13:47:21.607 に答える