首頁 > Java > java教程 > Java中如何有效率地繪製不斷變化的圖形?

Java中如何有效率地繪製不斷變化的圖形?

Patricia Arquette
發布: 2024-11-25 09:29:11
原創
425 人瀏覽過

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 計數器列印一秒內更新的幀數。

同步

:鎖防止並發繪畫,進一步提高穩定性。 這些最佳化帶來了效能的巨大提升,螢幕更新幾乎是瞬間出現的。 FPS 計數器提供了提高速度的衡量標準。

以上是Java中如何有效率地繪製不斷變化的圖形?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板