Repaint() 未在 JComponent 中调用 paintComponent() class

Repaint() not calling paintComponent() in JComponent class

我正在创建一个 java 应用程序,我在其中使用 JComponent class 进行绘制。 我遇到 repaint() 方法没有启动 paintComponent() 的问题。 这可能是什么原因造成的?

代码:

J组件类:

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

import javax.swing.JComponent;
import javax.swing.Timer;

public class Display extends JComponent implements ActionListener{

    private final static int Width = 400;
    private final static int Height = 600;
    private long period;
    private Timer timer;

    private Background background;

    private boolean isRunning = false;

    public Display(long period) {
        this.period = period;
        setSize(Width, Height);
        prepeareUi();
        setOpaque(false);
    }

    public void addNotify() {
        if(!isRunning) {
            timer = new Timer((int)period, this);
            timer.start();
            isRunning = true;
        }
    }

    public void stop() {
        if(isRunning)
            isRunning = false;
    }

    private void prepeareUi() {
        background = new Background(Width, Height);
    }

    public void paintComponent(Graphics g) {
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, Width, Height);
        background.draw(g);
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        if(isRunning) {
            background.update();
            repaint();
            return;
        }

        System.exit(0);

    }

}

帧class:

import javax.swing.JFrame;

public class Frame extends JFrame {

    private static final int DEFAULTFPS = 20;

    public Frame(long period) {
        prepearUI(period);
    }

    private void prepearUI(long period) {
        Display d = new Display(period);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(d);
        pack();
        setResizable(false);
        setVisible(true);
    }

    public static void main(String[]args) {
        String fpsS = null;
        if(args.length==1)
            fpsS = args[0];

        int fps = (fpsS != null) ? Integer.parseInt(fpsS) :  DEFAULTFPS;
        long period = (long) (1000.0/fps); //In Ms!

        Frame f = new Frame(period);
    }

}

背景class

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;


public class Background {

    private int ParentWidth;
    private int ParentHeight;

    private int width;
    private int height;

    private BufferedImage image;

    private float x = 0;
    private float y = 0;

    private final static float ANIMATIONSPEED = 1F;
    private final static int ANIMATION_RIGHT = 0;
    private final static int ANIMATION_LEFT = 1;

    private int animationway = 1;

    public Background(int W, int H) {
        ParentWidth = W;
        ParentHeight = H;
        prepeareImage();
    }

    private void prepeareImage() {
        width = 0; height = 0;
        try {
            image = ImageIO.read(getClass().getResource("UI\background.png"));
            width = image.getWidth(null);
            height = image.getHeight(null);
        } catch (IOException e) {
            System.err.println("Background.png not found!");
        }
    }

    public void update() {
        if(animationway == ANIMATION_RIGHT) {
            x += ANIMATIONSPEED;
            if(x>=0F) {
                animationway = ANIMATION_LEFT;
            }
        }

        if(animationway == ANIMATION_LEFT) {
            x -= ANIMATIONSPEED;
            if(x<=width/-1+ParentWidth) {
                animationway = ANIMATION_RIGHT;
            }
        }
    }

    public void draw(Graphics g) {
        g.drawImage(image, (int) x, (int) y, null);
    }

}

问题是您对 addNotify 的重写没有调用父级的实现。这破坏了很多东西,适当的重绘通知可能就是其中之一。您可以通过在实施中添加 super.addNotify(); 来解决此问题。

但我根本不会碰 addNotify。不要覆盖它。在构造函数中初始化计时器或添加父级可以调用以启动计时器的方法。您已经有了方法 stop(),所以只需创建方法 start()

JComponent.addNotify() 文档状态:

Notifies this component that it now has a parent component. When this method is invoked, the chain of parent components is set up with KeyboardAction event listeners. This method is called by the toolkit internally and should not be called directly by programs.

编辑:

为避免破坏绘制链,请确保在 paintComponent() 的实现中调用 super.paintComponent()。有关详细信息,请参阅 Performing Custom Painting and Painting in AWT and Swing