>Java >java지도 시간 >Java에서 끊임없이 변화하는 그래픽을 효율적으로 그리는 방법은 무엇입니까?

Java에서 끊임없이 변화하는 그래픽을 효율적으로 그리는 방법은 무엇입니까?

Patricia Arquette
Patricia Arquette원래의
2024-11-25 09:29:11439검색

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.