JPanel 背景加倍,但 Panel 正在按预期工作

JPanel background is doubled , but Panel is working expected

package com.company;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayDeque;
import java.util.Random;

public class REcom {
    REcom() {
        JFrame jfm = new JFrame("Paint");
        jfm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        BorderLayout border = new BorderLayout();
        border.setVgap(10);

        jfm.setLayout(border);


        DrawPanel dw = new DrawPanel();

        dw.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                dw.setXY(e.getX() , e.getY());
                dw.repaint();
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                dw.previosPosition = new Position(e.getX() , e.getY());

            }
        });


        jfm.add(dw  ,BorderLayout.CENTER);
        jfm.setBackground(Color.white);
        jfm.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
        jfm.setSize(500 ,500);

        JPanel color = new JPanel(new FlowLayout(FlowLayout.LEFT));
        //that Jpanel background is doubled
       // color.setBounds(new Rectangle(0 ,0 , 100 , jfm.getHeight()));

        Button blue = new Button();
        blue.setBackground(Color.blue);
        blue.setSize(500 ,200);
        blue.addActionListener(e -> {
            dw.color = Color.blue;
        });
        color.add(blue);

        Button white = new Button();
        white.setBackground(Color.white);
        white.setSize(200 ,200);
        white.addActionListener(e -> {
            dw.color = Color.white;
        });

        color.add(white);

        jfm.add(color , BorderLayout.NORTH);
        jfm.setPreferredSize(new Dimension(500 ,500));
        jfm.pack();
        color.setBackground(Color.blue);
        jfm.setVisible(true);

    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(REcom::new);
    }

}
class DrawPanel extends JPanel {
    ArrayDeque<Position> ad = new ArrayDeque<>();
    Position previosPosition = null;
    Color color = Color.yellow;
    void setXY(int x , int y) {
        ad.push(new Position(x , y));
    }
    @Override
    protected void paintComponent(Graphics g) {


        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(color);

        g2.setStroke(new BasicStroke(12f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
        Position d = ad.pollLast();

        if(d != null) {

            if(previosPosition == null)
                g2.fillOval(d.x, d.y -10 , d.x , d.y-10);
            else{

                g2.drawLine(previosPosition.x -5 , previosPosition.y -10 , d.x-5 , d.y-10);
            }

            previosPosition = d;
        }


    }

}
class Position {
    int x, y;
    Position(int x, int y) {
        this.x=  x;
        this.y = y;
    }
    void setXY(int x , int y) {
        this.x = x;
        this.y = y;
    }
}

关于代码:两个面板,一个用于绘图,另一个用于颜色之间的切换。我决定将切换器添加到框架的顶部。但是它的背景移到了底部,我可以在上面画画。(因此它的背景超出了边界)。如果我要为中央 JPanel 的面板(用于绘图)设置边框,则边框的顶部加倍
我想将 Jpanel 添加到顶部以在颜色(background is doubled after drawing anything)之间切换以进行绘图。但是顶层的Jpanel背景加倍了。但是,如果我将 Jpanel (color) 替换为通用面板,程序将正常运行。我不知道为什么?请帮忙!如果你不明白请尝试运行代码(我用翻译器写的这个问题)

JPanel background is doubled

自定义绘画时,方法中的第一条语句应该是:

super.paintComponent(g);

清除背景,否则会出现绘画伪像,这就是为什么您会看到两条蓝线。

当然,当您添加 super.paintComponent(g) 时,绘画会消失,因为背景已被清除。

问题有两种解决方案:

  1. 保留要绘制的对象的 ArrayList 并在 paintComponent() 方法中遍历 ArrayList 以绘制所有对象
  2. 绘制到 BufferedImage,然后绘制整个图像。

在这种情况下,我建议选项 2 可能是最好的。

查看 Custom Painting Approaches 了解每种方法的更多信息和示例。