繁体   English   中英

重绘线程不会重绘内部类JPanel

[英]Repainting-Thread doesn't repaint Inner-Class JPanel

我想在秋千上做一些下雨程序,但是由于某种原因,我无法从另一个班级重新粉刷面板。 这次我尝试为面板使用内部类,但是似乎无法从另一个类/线程重新粉刷它。 有人知道为什么吗?

sscce:

import javax.swing.JPanel;
import javax.swing.Timer;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;

public class UI extends JFrame {

    public static void main(String[] args) {
        UI myProgram = new UI();
        myProgram.setVisible(true);
    }

    public UI() {
        this.setSize(new Dimension(500,300));
        this.setBackground(Color.WHITE);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        UserPanel p = new UserPanel(this);
    }

    public class UserPanel extends JPanel implements ActionListener {

        private Timer time = new Timer(1, this);
        private UI myFrame;

        public UserPanel(UI myFrame) {
            this.myFrame = myFrame;
            this.setSize(myFrame.getSize());

            time.start();
        }

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

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            System.out.println("painting");
            g.setColor(Color.BLACK);
            g.fillRect(this.getWidth()/2, this.getHeight()/2, 50,50);
        }
    }
}

UI类(具有内部类JPanel):

package Rain;

import javax.swing.JPanel;
import javax.swing.Timer;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JFrame;

public class UI extends JFrame {


    public UI() {
        this.setSize(new Dimension(500,300));
        this.setBackground(Color.WHITE);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        UserPanel p = new UserPanel(this);
    }


    private class UserPanel extends JPanel implements ActionListener {

        private Timer time = new Timer(1, this);
        private UI myFrame;
        private ArrayList<Raindrop> rain = new ArrayList<Raindrop>();
        private static final int AMOUNT = 50;
        private Random rand = new Random();

        public UserPanel(UI myFrame) {
            this.myFrame = myFrame;
            this.setSize(myFrame.getSize());

            for(int i = 0; i < AMOUNT; i++) {
                createRain();
            }
            new Painter(this);
            time.start();
        }

        public void createRain() {
            float distance = rand.nextFloat() * 90 + 10;
            int x = rand.nextInt(this.getWidth());
            int y = 100;

            rain.add(new Raindrop(distance,x,y));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("tick");
            for(Raindrop r : rain) {
                r.fall();
            }
        }

        public void paintComponent(Graphics g) {
            System.out.println("painting");
            g.setColor(this.getBackground());
            g.fillRect(0,0,this.getWidth(),this.getHeight());
            for(Raindrop r : rain) {
                r.draw(g);
            }
        }

    }

}

画家:

package Rain;

import javax.swing.JPanel;

public class Painter extends Thread {

    private JPanel p;

    public Painter(JPanel p) {
        this.p = p;
        this.start();
    }

    public void run() {
        while(true) {
            System.out.println("trying to paint..");
            p.repaint();
        }
    }

}

控制台输出:

试图画..

试图画..

...

预期产量:

试图画..

绘画

试图画..

...

该线程确实有效,但是它从未在面板中调用paintComponent(Graphics g)函数

所有Swing应用程序都必须在自己的称为EDT的线程上运行。 (希望您通过调用SwingUtilities#invokelater方法来启动应用程序)。 因此,在事件调度线程之外重新绘制组件确实是一个糟糕的想法。 不用创建new Thread ,而是在javax.swing.Timer的动作侦听器中重新绘制组件,因为它将在EDT中运行。

@Override
public void actionPerformed(ActionEvent e) {
    System.out.println("tick");
    for(Raindrop r : rain) {
        r.fall();
    }
    repaint(); //repaint in EDT
}

另外,当您@Override paintComponent方法时,请始终通过调用super.paintComponent(g)

public void paintComponent(Graphics g) {
    super.paintComponent(g);//let component get painted normally
    System.out.println("painting");
    g.setColor(this.getBackground());
    g.fillRect(0,0,this.getWidth(),this.getHeight());
    for(Raindrop r : rain) {
        r.draw(g);
    }
}

在SSCCE之后更新

为了绘制组件,它必须有一个父对象。 您的UserPanel p = new UserPanel(this); 但您永远不会将其添加到框架中:

UserPanel p = new UserPanel(this);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(p);

完整的SSCCE:

public class UI extends JFrame {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> { //Run in EDT
            UI myProgram = new UI();
            myProgram.setVisible(true);
        });
    }

    public UI() {
        super("title");//call super for frame
        this.setSize(new Dimension(500, 300));
        this.setBackground(Color.WHITE);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        UserPanel p = new UserPanel(this);

        //Use border layout to make p fit the whole frame
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(p, BorderLayout.CENTER);
    }

    public class UserPanel extends JPanel implements ActionListener {

        private Timer time = new Timer(1, this);
        private UI myFrame;

        public UserPanel(UI myFrame) {
            this.myFrame = myFrame;
            this.setSize(myFrame.getSize());

            time.start();
        }

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

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            System.out.println("painting");
            g.setColor(Color.BLACK);
            g.fillRect(this.getWidth() / 2, this.getHeight() / 2, 50, 50);
        }
    }
}

不要忽略SwingUtilities.invokeLater

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM