Rumah  >  Artikel  >  Java  >  Bagaimana untuk Melukis Grafik yang Sentiasa Berubah di Java dengan Cekap?

Bagaimana untuk Melukis Grafik yang Sentiasa Berubah di Java dengan Cekap?

Patricia Arquette
Patricia Arquetteasal
2024-11-25 09:29:11374semak imbas

How to Efficiently Draw Constantly Changing Graphics in Java?

Cara Melukis Grafik yang Sentiasa Berubah dalam Java

Pengenalan

Mencipta grafik dinamik yang mengemas kini sentiasa boleh menjadi tugas yang mencabar di Jawa. Dalam artikel ini, kami akan menunjukkan cara untuk menangani perkara ini menggunakan teknik yang cekap dan penyegerakan benang.

Pernyataan Masalah

Kod awal yang disediakan dalam soalan mempunyai beberapa isu prestasi, mengakibatkan kemas kini grafik yang perlahan. Matlamatnya adalah untuk mengoptimumkan kod untuk mencapai kemas kini berterusan dengan kelajuan yang dipertingkatkan.

Kod Dioptimumkan

Berikut ialah versi yang dioptimumkan bagi kod:

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);
                                        }
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Penambahbaikan

  • Pengoptimuman Robot: Kaedah getPixelColor dalam kod asal adalah tidak cekap. Dengan menggunakan createScreenCapture untuk mengambil kesemua 64 piksel sekaligus, kami meningkatkan prestasi dengan ketara.
  • Keratan Pintar: Hanya kawasan yang diubah suai dicat semula, mengurangkan kemas kini yang tidak diperlukan.
  • Treading yang Diperbaiki: Model dan paparan dikemas kini pada Event Dispatch Benang, memastikan penyegerakan benang yang betul dan mengelakkan kemungkinan isu konkurensi.
  • Pemantauan FPS: Kaunter FPS mencetak bilangan bingkai yang dikemas kini dalam masa satu saat.
  • Penyegerakan : Kunci menghalang pengecatan serentak, bertambah baik kestabilan.

Pengoptimuman ini menghasilkan peningkatan besar dalam prestasi, dengan kemas kini skrin muncul hampir serta-merta. Kaunter FPS menyediakan ukuran kelajuan yang dipertingkatkan.

Atas ialah kandungan terperinci Bagaimana untuk Melukis Grafik yang Sentiasa Berubah di Java dengan Cekap?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn