ホームページ >Java >&#&チュートリアル >Java で絶えず変化するグラフィックスを効率的に描画するには?

Java で絶えず変化するグラフィックスを効率的に描画するには?

Patricia Arquette
Patricia Arquetteオリジナル
2024-11-25 09:29:11435ブラウズ

How to Efficiently Draw Constantly Changing Graphics in Java?

Java で絶えず変化するグラフィックスを描画する方法

はじめに

更新される動的グラフィックスの作成Java では常に困難な作業となる可能性があります。この記事では、効率的な手法とスレッド同期を使用してこれに対処する方法を示します。

問題の説明

質問で提供された最初のコードには、いくつかのパフォーマンスの問題がありました。その結果、グラフィックの更新が遅くなります。目標は、コードを最適化して、速度を向上させながら継続的な更新を実現することです。

最適化されたコード

これは、コード:

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;

    // Model to hold pixel colors
    private final Color[][] model = new Color[8][8];

    // Flag to prevent concurrent painting
    private boolean isDrawing = false;

    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);
    }

    // Sets the pixel color at the given position
    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);
    }

    // Gets the pixel color at the given position
    private Color getColorAt(int x, int y) {
        return model[x][y];
    }

    // Draws the graphics
    public void paintComponent(Graphics g) {
        long start = System.currentTimeMillis();

        if (!SwingUtilities.isEventDispatchThread()) {
            throw new RuntimeException("Repaint attempt is not on event dispatch thread");
        }

        // Prevent concurrent painting
        isDrawing = true;

        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++;

        // Display FPS count
        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);

        // Allow painting again
        isDrawing = false;
    }

    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);

                // Synchronized block to prevent concurrent access to the model
                synchronized (view) {
                    // If the panel is not drawing, update the model and repaint
                    if (!view.isDrawing) {
                        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);
                                        }
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

改善点

  • ロボットの最適化: 元のコードの getPixelColor メソッドは非効率的でした。 createScreenCapture を使用して 64 ピクセルすべてを一度に取得することで、パフォーマンスが大幅に向上します。
  • スマート クリッピング: 変更された領域のみが再描画され、不要な更新が削減されます。
  • スレッド処理の改善: モデルとビューはイベント ディスパッチ スレッドで更新され、適切なスレッド同期が保証され、スレッドの同期が回避されます。潜在的な同時実行の問題。
  • FPS モニタリング: FPS カウンターは 1 秒以内に更新されたフレーム数を出力します。
  • 同期: ロックにより同時実行が防止されます。ペイントにより、安定性がさらに向上します。

これらの最適化により、画面の更新がほぼ瞬時に行われるため、パフォーマンスが向上します。 FPS カウンターは、改善された速度の尺度を提供します。

以上がJava で絶えず変化するグラフィックスを効率的に描画するには?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。