> Java > java지도 시간 > 본문

성능을 향상시키기 위해 마우스 위치에 따라 지속적으로 변화하는 그래픽을 그리는 Java 코드를 어떻게 최적화할 수 있습니까?

Barbara Streisand
풀어 주다: 2024-11-23 09:14:21
원래의
760명이 탐색했습니다.

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(Event Dispatch Thread)와 동기화되지 않아 그래픽 오류가 발생할 수 있습니다.

성능 향상

이러한 문제를 완화하려면 다음 최적화를 고려하십시오.

  1. 더 빠른 픽셀 가져오기를 위해 createScreenCapture 활용: 개별 픽셀을 검색하는 대신 robots.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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿