Java动画冻结

时间:2014-08-12 03:14:43

标签: java animation jframe jpanel refresh

我正在尝试用Java编写一个简单的2d动画引擎,用于可视化以后的编程项目。但是,我在窗口刷新时遇到问题。在运行时,框架有时会显示空白面板而不是所需图像。这开始时会以明显随机的间隔一次开始几帧,随着程序继续运行而恶化,直到实际图像偶尔闪烁进入视图。运行处理每个帧的代码,但实际上不显示帧中的任何内容。我相信问题可能来自我的电脑而不是我的代码(当然不是来自糟糕的规格),但我不确定。非常感谢。

三节课。代码在这里:

package animator;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.applet.AudioClip;

public class APanel extends JPanel
{

    public APanel(int l, int h){

        setPreferredSize(new Dimension(l,h));
        setLocation(80, 80);
        setVisible(true);
        setFocusable(true);     

    }

    public Graphics renderFrame(Graphics g){

        return g;

    }   

    public void paintComponent(Graphics g) {

        requestFocusInWindow();
        renderFrame(g);

    }

}

package animator;

import java.awt.*;

public class Animator extends APanel
//extending the APanel class allows you to code for different animations
//while leaving the basic functional animator untouched
{

    public static final int SCREEN_X = 700;
    public static final int SCREEN_Y = 700;

    int frameNum;

    public Animator() {
        super(SCREEN_X, SCREEN_Y);
        frameNum = 0;
    }

    public Graphics renderFrame(Graphics g) {

        frameNum++;
        g.drawString(""+frameNum,5,12);
        return g;

    }

}

package animator;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;

public class Runner {

   int framerate = 30;
    Animator a = new Animator();
    JFrame j = new JFrame();

    public Runner(){
        j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        j.add(a);
        start();
        j.setSize(a.getPreferredSize());
        j.setVisible(true);
    }

    public void start() {
        Timer t = new Timer(1000/framerate, new ActionListener() {

            public void actionPerformed(ActionEvent e){
                j.getComponent(0).paint(j.getComponent(0).getGraphics());

                //The following line of code keeps the window locked to a preferred size
//                j.setSize(j.getComponent(0).getPreferredSize());
            }

        });
        t.start();
    }

    public static void main(String[] args){
        Runner r = new Runner();
    }

}

1 个答案:

答案 0 :(得分:0)

您的代码中存在一些严重错误,可能是您的问题的原因或因素......

  • j.setSize(a.getPreferredSize());无关紧要,只需使用JFrame#pack即可获得更好的结果,因为它会考虑到框架装饰
  • j.setSize(j.getComponent(0).getPreferredSize());使用JFrame#setResizable并将其传递给false而不是......
  • 永远不要j.getComponent(0).paint(j.getComponent(0).getGraphics());这个!您不负责在Swing中绘制组件,这是RepaintManager的决定。只需致电j.repaint()
  • 即可
  • super(SCREEN_X, SCREEN_Y); ...只需覆盖getPreferredSize方法并返回您想要的尺寸。
  • setLocation(80, 80);无关紧要,因为该组件受布局管理器控制
  • setVisible(true);(在APanel内)...默认情况下,Swing组件已经可见,但窗口和JInternalFrame s
  • 除外

最后......

public void paintComponent(Graphics g) {
    requestFocusInWindow();
    renderFrame(g);
}

永远不需要制作这种方法public,你永远不希望有人能够调用它,这会破坏油漆链,并可能对组件绘制的能力产生严重影响本身就好了。

你必须在执行任何自定义绘画之前调用super.paintComponent,否则你可能会得到各种精彩的绘画文物和问题

永远不要在paint方法中修改组件的状态......当它"可能"在您的requestFocusInWindow();中调用paintComponent可能会产生您不了解的副作用......

相反,它应该看起来更像......

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    renderFrame(g);
}