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