パフォーマンスを向上させるために、マウスの位置に基づいて継続的に変化するグラフィックスを描画するために Java コードを最適化するにはどうすればよいですか?

Barbara Streisand
リリース: 2024-11-23 09:14:21
オリジナル
761 人が閲覧しました

How can I optimize Java code for drawing continuously changing graphics based on mouse position to improve performance?

Java: 連続的に変化するグラフィックスの描画

このプログラムでは、ユーザーのマウスの位置に基づいて連続的に変化する画像を描画しようとします。パフォーマンスの問題が発生し、最適化のためのガイダンスを探しています。コードを詳しく調べて課題に対処しましょう:

元のコード

初期実装は、いくつかの要因によりパフォーマンス上の欠点があります:

  1. 非効率ピクセルの取得: 個々のピクセルを取得するには robot.getPixelColor(...) を使用しますが、これは複数のピクセルを一度に取得します。
  2. 冗長な再描画: このコードは、ほんの一部が変更されている場合でもイメージ全体を再描画するため、不必要な再描画操作が発生します。
  3. 間違ったスレッド: モデルとビューの更新がイベント ディスパッチ スレッドと同期されません。 (EDT) により、グラフィックの不一致が発生する可能性があります。

パフォーマンスの強化

これらの問題を軽減するには、次の最適化を検討してください。

  1. より高速なピクセル取得のための createScreenCapture: の代わりに個々のピクセルを取得するには、robot.createScreenCapture(...) を使用して 64 ピクセルすべてを一度にフェッチし、パフォーマンスを向上させます。
  2. 効率的な再描画のためのスマート クリッピングの実装: 画像の正確な領域を決定します。再描画する必要がある部分のみを再描画することで、不必要な再描画を最小限に抑えます。操作。
  3. EDT 同期の確保: SwingUtilities.invokeLater(...) を使用してイベント ディスパッチ スレッド (EDT) でモデルとビューを更新し、スレッドの安全性を確保し、グラフィックアーティファクトを防ぎます。

最適化されたコード

例を示しますパフォーマンスの問題に対処するコードの最適化されたバージョン:

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;

public class ZoomPanel extends JPanel {

    private static final int STEP = 40;
    private int iter = 0;
    private long cumulativeTimeTaken = 0;

    public static void main(String[] args) {
        final JFrame frame = new JFrame("Image zoom");

        final ZoomPanel zoomPanel = new ZoomPanel();
        frame.getContentPane().add(zoomPanel);
        final Ticker t = new Ticker(zoomPanel);

        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                t.done();
                frame.dispose();
            }
        });
        t.start();

        frame.setLocation(new Point(640, 0));
        frame.pack();
        frame.setVisible(true);
    }

    private final Color[][] model = new Color[8][8];

    public ZoomPanel() {
        setSize(new Dimension(400, 400));
        setMinimumSize(new Dimension(400, 400));
        setPreferredSize(new Dimension(400, 400));
        setOpaque(true);
    }

    private void setColorAt(int x, int y, Color pixelColor) {
        model[x][y] = pixelColor;
        repaint(40 + x * STEP, 45 + y * STEP, 40 + (x * STEP) - 3, 45 + (y * STEP) - 3);
    }

    private Color getColorAt(int x, int y) {
        return model[x][y];
    }

    public void paintComponent(Graphics g) {
        long start = System.currentTimeMillis();
        if (!SwingUtilities.isEventDispatchThread()) {
            throw new RuntimeException("Repaint attempt is not on event dispatch thread");
        }
        final Graphics2D g2 = (Graphics2D) g;
        g2.setColor(getBackground());
        try {

            for (int x = 0; x < 8; x++) {
                for (int y = 0; y < 8; y++) {
                    g2.setColor(model[x][y]);
                    Ellipse2D e = new Ellipse2D.Double(40 + x * STEP, 45 + y * STEP, STEP - 3, STEP - 3);
                    g2.fill(e);
                    g2.setColor(Color.GRAY);
                    g2.draw(e);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        iter++;
        g2.setColor(Color.black);
        long stop = System.currentTimeMillis();
        cumulativeTimeTaken += stop - start;
        StringBuilder sb = new StringBuilder();
        sb.append(iter)
                .append(" frames in ")
                .append((double) (cumulativeTimeTaken) / 1000)
                .append("s.");

        System.out.println(sb);
    }

    private static class Ticker extends Thread {

        private final Robot robot;

        public boolean update = true;
        private final ZoomPanel view;

        public Ticker(ZoomPanel zoomPanel) {
            view = zoomPanel;
            try {
                robot = new Robot();
            } catch (AWTException e) {
                throw new RuntimeException(e);
            }
        }

        public void done() {
            update = false;
        }

        public void run() {
            int runCount = 0;
            while (update) {
                runCount++;
                if (runCount % 100 == 0) {
                    System.out.println("Ran ticker " + runCount + " times");
                }
                final Point p = MouseInfo.getPointerInfo().getLocation();

                Rectangle rect = new Rectangle(p.x - 4, p.y - 4, 8, 8);
                final BufferedImage capture = robot.createScreenCapture(rect);

                for (int x = 0; x < 8; x++) {
                    for (int y = 0; y < 8; y++) {
                        final Color pixelColor = new Color(capture.getRGB(x, y));

                        if (!pixelColor.equals(view.getColorAt(x, y))) {
                            final int finalX = x;
                            final int finalY = y;
                           SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                    view.setColorAt(finalX, finalY, pixelColor);
                                }
                            });
                        }
                    }
                }

            }
        }

    }

}
ログイン後にコピー

この最適化されたコードは、効率的なピクセル取得のために createScreenCapture を採用し、選択的再描画のためにスマート クリッピングを実装し、スレッド セーフのために EDT 同期を保証します。これらのパフォーマンスのボトルネックに対処することで、よりスムーズで応答性の高いグラフィック出力が提供されます。

以上がパフォーマンスを向上させるために、マウスの位置に基づいて継続的に変化するグラフィックスを描画するために Java コードを最適化するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート