编程语言
首页 > 编程语言> > java – 出现在JPanel上的Visual Artifacts

java – 出现在JPanel上的Visual Artifacts

作者:互联网

我正在尝试使用BorderLayout创建一个包含2个JPanel的程序.中间面板用于随机绘制矩形,而南面板用于按钮.

每当我将鼠标光标悬停在北或南按钮上时,我会得到JFrame左上角按钮的奇怪图像.我做了一些研究,发现这可能是拥有透明背景的原因.我尝试使用super.paintComponent(g)作为面板,但之前绘制的其余矩形消失了.我需要将矩形留在JPanel中,而不是左上角的奇怪图像.

我不知道我做错了什么,希望有人可以帮助或提供一些如何解决这个问题的线索.

    public class TwoBRandomRec extends JFrame{

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        TwoBRandomRec rec = new TwoBRandomRec();

        rec.setSize(500,500);
        rec.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        rec.setVisible(true);
    }

    public TwoBRandomRec() {
        //Create the buttons
        JButton north = new JButton("North");
        JButton south = new JButton("South");
        DrawPanel drawPanel = new DrawPanel(500,500);

        JPanel southP = new JPanel();
        southP.add(south);
        southP.add(north);

        this.add(drawPanel, BorderLayout.CENTER);
        this.add(southP, BorderLayout.SOUTH);

        this.setTitle("TwoButtonRandomRec");
        this.pack();        
    }

    public class DrawPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        private Random rand = new Random();
        private int x,y,xSize,ySize;
        private int height,width;

        public DrawPanel(int w,int h) {
            width = w;
            height = h;
        }
        public void RandomX(){
             x=rand.nextInt(width-1);
             xSize=rand.nextInt(width-x);
         }

         public void RandomY(){
             y=rand.nextInt(height-1);
             ySize=rand.nextInt(height-y);
         }

         public Color RandomColour(){
             rand.nextInt(height);
             return new Color(rand.nextInt(255),rand.nextInt(255),rand.nextInt(255));
         }

        @Override
        protected void paintComponent(Graphics g) {
            RandomX();
            RandomY();

            g.setColor(RandomColour());
            g.fillRect(x, y, xSize, ySize);
            try {
                Thread.sleep(50);

            } catch (InterruptedException e) {  
            }

            repaint();
        }
    }
}

解决方法:

你不是在调用super.paintComponent

protected void paintComponent(Graphics g) {
    super.paintComponent(g); // <-- Insert me here and watch problem go away
    RandomX();
    RandomY();

    g.setColor(RandomColour());
    g.fillRect(x, y, xSize, ySize);
    try {
        Thread.sleep(50); // <-- This is an INCREDIBLY bad idea, NEVER, EVER do this

    } catch (InterruptedException e) {  
    }

    repaint(); // <-- This is a bad idea, watch CPU max out...
}

您有义务调用super.paintComponent以确保正确支持绘制链,并且会发生诸如不透明度和清理图形上下文之类的事情.

Graphics对象通过单个重绘传递在组件之间共享,如果不遵守正确的绘制链,将导致像你这样的问题

永远不要从任何绘制方法更新UI(这包括调用重绘),这只会导致你的绘制方法被一遍又一遍地重新调用……直到你的CPU达到100%并且程序挂起.

从来没有,在绘画方法(或一般用户界面)中做任何时间消耗或阻止操作,这将使它看起来像程序挂起并使用户不安(你认为僵尸群体是坏的:P).以这种方式阻止会阻止EDT响应绘制请求…

我建议你仔细阅读:

> Performing Custom Painting
> 2D Graphics
> Painting in AWT and Swing
> Concurrency in Swing

标签:repaint,paintcomponent,java,swing,jpanel
来源: https://codeday.me/bug/20190929/1832693.html