Maison > Java > javaDidacticiel > Pourquoi l'ajout et la concentration sur un JTextField sur un JPanel animé à double tampon dans Swing provoquent-ils des problèmes de scintillement sur Mac OS X 10.5 avec Java 1.6 ?

Pourquoi l'ajout et la concentration sur un JTextField sur un JPanel animé à double tampon dans Swing provoquent-ils des problèmes de scintillement sur Mac OS X 10.5 avec Java 1.6 ?

Mary-Kate Olsen
Libérer: 2024-12-28 05:52:10
original
210 Les gens l'ont consulté

Why does adding and focusing on a JTextField over a double-buffered animated JPanel in Swing cause flickering issues on Mac OS X 10.5 with Java 1.6?

JTextFields au-dessus du dessin actif sur JPanel, problèmes de thread

Swing peut être utilisé pour créer un environnement de rendu multi-tampon approprié par-dessus desquels des éléments d'interface utilisateur Swing peuvent être ajoutés. Dans ce cas, nous avons un rectangle rouge animé dessiné sur un arrière-plan. L'arrière-plan n'a pas besoin d'être mis à jour à chaque image, nous le rendons donc sur une BufferedImage et redessinons uniquement la partie nécessaire pour effacer l'emplacement précédent du rectangle.

Jusqu'ici tout va bien ; animation fluide, faible utilisation du processeur, pas de scintillement. Ensuite, nous ajoutons un JTextField au Jpanel (en cliquant sur n'importe quelle position de l'écran) et nous nous concentrons dessus en cliquant à l'intérieur de la zone de texte. La suppression de l'emplacement précédent du rectangle échoue désormais à chaque clignotement du curseur, voir l'image ci-dessous.

Nous sommes curieux de savoir si quelqu'un a une idée de la raison pour laquelle cela pourrait se produire (Swing n'est pas thread-safe ? L'image en cours de peinture de manière asynchrone ?) et dans quelle direction chercher les solutions possibles.

C'est sur Mac OS 10.5, Java 1.6.

NouveauTest étend JPanel ; mais comme vous ne peignez pas chaque pixel à chaque appel à paintComponent(), vous devez invoquer la méthode de la super-classe et effacer l'ancien dessin :

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int width = this.getWidth();
    int height = this.getHeight();
    g.setColor(Color.black);
    g.fillRect(0, 0, width, height);
    ...
}
Copier après la connexion

Addendum : comme vous le notez, définition de l'arrière-plan color dans le constructeur exclut la nécessité de remplir le panneau dans paintComponent(), tandis que super.paintComponent() permet au(x) champ(s) de texte de fonctionner correctement. Comme vous le constatez, la solution de contournement proposée est fragile. Au lieu de cela, simplifiez le code et optimisez-le si nécessaire. Par exemple, vous n'aurez peut-être pas besoin de la complication des encarts, des tampons supplémentaires et d'un écouteur de composant.

Addendum 2 : Notez que super.paintComponent() appelle la méthode update() du délégué de l'interface utilisateur, "qui remplit le composant spécifié avec sa couleur de fond (si sa propriété opaque est vraie)." Vous pouvez utiliser setOpaque(false) pour empêcher cela.

Une version encore améliorée du code, avec quelques fonctionnalités et optimisations supplémentaires :

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;

/** @see http://stackoverflow.com/questions/3256941 */
public class AnimationTest extends JPanel implements ActionListener {

    private static final int WIDE = 640;
    private static final int HIGH = 480;
    private static final int RADIUS = 25;
    private static final int FRAMES = 24;
    private final Timer timer = new Timer(20, this);
    private final Rectangle rect = new Rectangle();
    private BufferedImage background;
    private int index;
    private long totalTime;
    private long averageTime;
    private int frameCount;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new AnimationTest().create();
            }
        });
    }

    private void create() {
        JFrame f = new JFrame("AnimationTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        timer.start();
    }

    public AnimationTest() {
        super(true);
        this.setOpaque(false);
        this.setPreferredSize(new Dimension(WIDE, HIGH));
        this.addMouseListener(new MouseHandler());
        this.addComponentListener(new ComponentHandler());
    }

    @Override
    protected void paintComponent(Graphics g) {
        long start = System.nanoTime();
        super.paintComponent(g);
        int w = this.getWidth();
        int h = this.getHeight();
        g.drawImage(background, 0, 0, this);
        double theta = 2 * Math.PI * index++ / 64;
        g.setColor(Color.blue);
        rect.setRect(
            (int) (Math.sin(theta) * w / 3 + w / 2 - RADIUS),
            (int) (Math.cos(theta) * h / 3 + h / 2 - RADIUS),
            2 * RADIUS, 2 * RADIUS);
        g.fillOval(rect.x, rect.y, rect.width, rect.height);
        g.setColor(Color.white);
        if (frameCount == FRAMES) {
            averageTime = totalTime / FRAMES;
            totalTime = 0; frameCount = 0;
        } else {
            totalTime += System.nanoTime() - start;
            frameCount++;
        }
        String s = String.format("%1.3f", averageTime / 1000000d);
        g.drawString(s, 5, 16);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        this.repaint();
    }

    private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            super.mousePressed(e);
            JTextField field = new JTextField("test");
            Dimension d = field.getPreferredSize();
            field.setBounds(e.getX(), e.getY(), d.width, d.height);
            add(field);
        }
    }

    private class ComponentHandler extends ComponentAdapter {

        private final GraphicsEnvironment ge =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        private final GraphicsConfiguration gc =
            ge.getDefaultScreenDevice().getDefaultConfiguration();
        private final Random r = new Random();

        @Override
        public void componentResized(ComponentEvent e) {
            super.componentResized(e);
            int w = getWidth();
            int h = getHeight();
            background = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
            Graphics2D g = background.createGraphics();
            g.clearRect(0, 0, w, h);
            g.setColor(Color.green.darker());
            for (int i = 0; i < 128; i++) {
                g.drawLine(w / 2, h / 2, r.nextInt(w), r.nextInt(h));
            }
            g.dispose();
            System.out.println("Resized to " + w + " x " + h);
        }
    }
}
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal