首页 > Java > java教程 > 正文

如何优化 Java 代码以根据鼠标位置绘制连续变化的图形以提高性能?

Barbara Streisand
发布: 2024-11-23 09:14:21
原创
762 人浏览过

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
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板