Maison >Java >javaDidacticiel >Comment puis-je optimiser le code Java pour dessiner des graphiques en constante évolution en fonction de la position de la souris afin d'améliorer les performances ?

Comment puis-je optimiser le code Java pour dessiner des graphiques en constante évolution en fonction de la position de la souris afin d'améliorer les performances ?

Barbara Streisand
Barbara Streisandoriginal
2024-11-23 09:14:21838parcourir

How can I optimize Java code for drawing continuously changing graphics based on mouse position to improve performance?

Java : dessiner des graphiques en constante évolution

Dans ce programme, vous cherchez à dessiner une image en constante évolution en fonction de la position de la souris de l'utilisateur. Vous avez rencontré des problèmes de performances et recherchez des conseils d’optimisation. Examinons votre code et relevons les défis :

Le code d'origine

La mise en œuvre initiale souffre de problèmes de performances dus à plusieurs facteurs :

  1. Inefficace Récupération de pixels : Vous utilisez robot.getPixelColor(...) pour récupérer des pixels individuels, ce qui est nettement plus lent que la récupération de plusieurs pixels à la fois. une fois.
  2. Redessin redondant :Le code redessine l'intégralité de l'image même si seule une petite partie a changé, ce qui entraîne des opérations de repeinture inutiles.
  3. Threading incorrect : Les mises à jour du modèle et de la vue ne sont pas synchronisées avec le fil de répartition d'événement (EDT), ce qui peut provoquer des problèmes graphiques. incohérences.

Améliorations des performances

Pour atténuer ces problèmes, envisagez les optimisations suivantes :

  1. Utilisez createScreenCapture pour une récupération plus rapide des pixels : Au lieu de récupérer des pixels individuels, utilisez robot.createScreenCapture(...) pour récupérez les 64 pixels à la fois, améliorant ainsi les performances.
  2. Implémentez un découpage intelligent pour un redessinage efficace : Déterminez la région exacte de l'image qui doit être redessinée et repeignez uniquement cette partie, minimisant ainsi les redessinements inutiles. opérations.
  3. Assurer la synchronisation EDT : Mettre à jour le modèle et la vue dans l'événement Dispatch Thread (EDT) utilisant SwingUtilities.invokeLater(...) pour garantir la sécurité des threads et éviter les artefacts graphiques.

Code optimisé

Voici un exemple de version optimisée du code qui répond aux problèmes de performances :

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

            }
        }

    }

}

Ce code optimisé utilise createScreenCapture pour une récupération efficace des pixels, implémente des fonctionnalités intelligentes découpage pour un redessinage sélectif et assure la synchronisation EDT pour la sécurité des threads. En résolvant ces goulots d'étranglement en termes de performances, il fournit une sortie graphique plus fluide et plus réactive.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn