Repaint()不在JComponent类中调用paintComponent()

时间:2015-01-05 01:04:24

标签: java swing jcomponent

我正在创建一个java应用程序,我使用JComponent类进行绘制。 我有一个问题,repaint()方法没有启动paintComponent()。 造成这种情况的原因是什么?

代码:

JComponent类:

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);

    }

}

框架类:

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);
    }

}

背景课

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);
    }

}

1 个答案:

答案 0 :(得分:4)

问题是你的addNotify覆盖没有调用父实现。这打破了许多事情,适当的重新通知可能就是其中之一。您可以通过向您的实施添加super.addNotify();来解决此问题。

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

JComponent.addNotify()文档声明:

  

通知此组件它现在有一个父组件。当这个   调用方法,设置父组件链   KeyboardAction事件侦听器。该方法由工具包调用   在内部,不应该由程序直接调用。

编辑:

为避免破坏油漆链,请务必在super.paintComponent()的实施中致电paintComponent()。有关详细信息,请参阅Performing Custom PaintingPainting in AWT and Swing