首頁 > Java > java教程 > 主體

如何優化 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. 效率低下像素取得: 您使用robots.getPixelColor(...)來檢索單一像素,這比在以下位置獲取多個像素要慢得多
  2. 冗餘重繪:即使只有一小部分發生變化,程式碼也會重繪整個影像,從而導致不必要的重繪操作。
  3. 不正確的執行緒: 模型和視圖的更新與事件調度執行緒(EDT)不同步,這可能會導致圖形

效能增強

要緩解這些問題,請考慮以下最佳化:

  1. 利用createScreenCapture 加速像素取得速度: 使用robots.createScreenCapture(...) 來取得所有像素,而不是檢索單一像素一次 64 像素,增強效能。
  2. 實現智慧裁剪以實現高效重繪:確定影像中需要重繪的確切區域,並僅重繪該部分,最大限度地減少不必要的重繪操作。
  3. 確保 EDT 同步: 更新事件調度中的模型和視圖線程 (EDT) 使用 SwingUtilities.invokeLater(...) 確保線程安全並防止圖形偽影。

最佳化程式碼

以下是程式碼最佳化版本的範例,解決了效能問題:

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中文網其他相關文章!

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