paintComponent disegna altri componenti sopra il mio disegno

Sto cercando di creare un semplice strumento di disegno. Gli eventi mouseDrag creano una nuova ellisse e causa il repaint() mio JPanel repaint() .

Questo funziona bene finora. Tuttavia, se premo un pulsante qualsiasi (o qualsiasi altro componente dell’interfaccia utente) prima di mouseDrag evento mouseDrag per la prima volta, il pulsante viene dipinto nell’angolo in alto a sinistra del mio pannello.

Ho isolato il codice in questa applicazione di test:

 import java.awt.BasicStroke; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Test extends JFrame { public Test() { final JPanel paintPanel = new JPanel(){ @Override protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D)g; g2d.setPaintMode(); g2d.setStroke(new BasicStroke(1)); g2d.fillRect(100, 100, 10, 10); } }; paintPanel.setPreferredSize(new Dimension(300,300)); paintPanel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { paintPanel.repaint(); } }); this.setLayout(new FlowLayout()); this.add(paintPanel); this.add(new JButton("Dummy")); this.pack(); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String... args) { new Test(); } } 

TestApp prima di fare clic sul pannelloTestApp dopo aver fatto clic sul pannello

Uno screenshot per “vedere” il problema nella mia applicazione principale

+1 alle risposte @ MadProgrammer.

  • Dovresti avere super.paintComponent(..) come prima chiamata nel tuo overriden paintComponent()
  • Non estendere JFrame inutilmente
  • Crea e calcola i componenti di Swing tramite EDT
  • Non chiamare setPrefferedSize() piuttosto sovrascrivere getPrefferedSize()

Ecco un esempio che incorpora i miei consigli e @ MadProgrammer:

inserisci la descrizione dell'immagine qui

 import java.awt.BasicStroke; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class Test { JFrame frame; public Test() { frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final PaintPanel paintPanel = new PaintPanel(); paintPanel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { paintPanel.addRect(e.getX(), e.getY()); } }); frame.setLayout(new FlowLayout()); frame.add(paintPanel); frame.add(new JButton("Dummy")); frame.pack(); frame.setVisible(true); } public static void main(String... args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Test(); } }); } } class PaintPanel extends JPanel { public PaintPanel() { addRect(100, 100); } ArrayList rects = new ArrayList<>(); @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setPaintMode(); for (Rectangle r : rects) { g2d.setStroke(new BasicStroke(1)); g2d.fillRect(rx, ry, r.width, r.height); } } public void addRect(int x, int y) { rects.add(new Rectangle(x, y, 10, 10)); repaint(); } @Override public Dimension getPreferredSize() { return new Dimension(300, 300); } } 

Non stai chiamando super.paintComponent .

Il contesto grafico utilizzato per un ciclo pittorico è condiviso tra tutti i componenti che iniziano a dipingere, questo significa che se non si cura di eliminarlo prima di dipingere, si finirà con ciò che è stato dipinto prima di te.

Uno dei compiti di paintComponent è quello di preparare la grafica per la pittura