简体   繁体   中英

Repaint() is not being called in Java while loop

I'm attempting to create a simple animation in Java that displays a blue ball moving horizontally part way across a 500 x 500 window. The ball is supposed to move at a rate of 1px/30ms. The problem is, is that the window is only being painted when the while loop exits and not during every iteration of the while loop as I intended. This results in the blue ball being painted in its final location. Could you please tell me what I'm doing wrong here? I've also tried executing this code on the EDT with the paintComponent() method and got the same result. In addition, as suggested by other posts, I got the same result when using paintImmediately(0, 0, getWidth(), getHeight()) instead of repaint() while using the EDT and paintComponent() method. I'm trying to do all of this without using timers.

import javax.swing.*;
import java.awt.*;

class AnimationFrame extends JPanel {

    int ovalX = 50;
    long animDuration = 5000;
    long currentTime = System.nanoTime() / 1000000;
    long startTime = currentTime;
    long elapsedTime = currentTime - startTime;

    public AnimationFrame() {
        setPreferredSize(new Dimension(500, 500));
        runAnimation();
    }

    public void runAnimation() {
        while (elapsedTime < animDuration) {
            currentTime = System.nanoTime() / 1000000;
            elapsedTime = currentTime - startTime;
            System.out.println(elapsedTime);
            ovalX = ovalX + 1;
            try {
                Thread.sleep(30);
            }
            catch (Exception e) {
            }
            repaint();
        }
    }

    public void paint(Graphics g) {
        Rectangle clip = g.getClipBounds();
        g.setColor(Color.BLACK);
        g.fillRect(clip.x, clip.y, clip.width, clip.height);
        g.setColor(Color.BLUE);
        g.fillOval(ovalX, 250, 70, 70);
    }

    public static void main(String[] args) {
        createAndShowGUI();
    }

    public static void createAndShowGUI() {
        JFrame mainFrame = new JFrame();
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.add(new AnimationFrame());
        mainFrame.pack();
        mainFrame.setVisible(true);
    }
}

I looked at your code and noticed that you are calling the method that runs the animation from within the constructor of the "AnimationFrame" which you are adding to your "mainFrame".

The problems with doing it that way is that you are trying to animate before the object has finished being constructed, which must be completed before it can be added to the mainFrame, which is not yet made to be visible on the screen.

I made the follow changes to your code and I see a blue ball move across the frame now.

import javax.swing.*;
import java.awt.*;

class AnimationFrame extends JPanel {

    int ovalX = 50;
    long animDuration = 5000;
    long currentTime = System.nanoTime() / 1000000;
    long startTime = currentTime;
    long elapsedTime = currentTime - startTime;

    public AnimationFrame() {
        setPreferredSize(new Dimension(500, 500));
        //i removed the call to runAnimation from here

    }

    public void runAnimation() {
        while (elapsedTime < animDuration) {
            currentTime = System.nanoTime() / 1000000;
            elapsedTime = currentTime - startTime;
            System.out.println(elapsedTime);
            ovalX = ovalX + 1;
            try {
                Thread.sleep(30);
            }
            catch (Exception e) {
            }
            repaint();
        }
    }

    @Override
    public void paint(Graphics g) {
        Rectangle clip = g.getClipBounds();
        g.setColor(Color.BLACK);
        g.fillRect(clip.x, clip.y, clip.width, clip.height);
        g.setColor(Color.BLUE);
        g.fillOval(ovalX, 250, 70, 70);
    }

    public static void main(String[] args) {
        createAndShowGUI();
    }

    public static void createAndShowGUI() {
        JFrame mainFrame = new JFrame();
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        AnimationFrame animationPanel = new AnimationFrame();
        mainFrame.add(animationPanel);
        mainFrame.pack();
        mainFrame.setVisible(true);
        //I made the call to runAnimation here now
        //after the containing frame is visible.
        animationPanel.runAnimation();
    }
}

You need to do the loop in a separate thread. See this tutorial- http://101.lv/learn/Java/ch10.htm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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