Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 重新绘制方法会因短暂延迟而停止工作_Java_Swing - Fatal编程技术网

Java 重新绘制方法会因短暂延迟而停止工作

Java 重新绘制方法会因短暂延迟而停止工作,java,swing,Java,Swing,我试图创建一个简单的面板,其中一个二维球上下弹跳。我无法让它工作,因为出于某种原因,我不能每秒多次调用repait方法。该设计基本上是通过方法move()给一个对象一个“脉冲”。每次调用evaluatePosition方法时,都会通过经过的时间、速度和加速度计算当前位置。面板的代码为: public class Display extends JPanel { private MovableObject object = new MovableObject(new Ellipse2D.Dou

我试图创建一个简单的面板,其中一个二维球上下弹跳。我无法让它工作,因为出于某种原因,我不能每秒多次调用repait方法。该设计基本上是通过方法
move()
给一个对象一个“脉冲”。每次调用
evaluatePosition
方法时,都会通过经过的时间、速度和加速度计算当前位置。面板的代码为:

public class Display extends JPanel {
  private MovableObject object = new MovableObject(new Ellipse2D.Double(5,5,50,50));
  private static final int DELAY = 1000;

  public Display(){
    object.move(50,50);
    Timer timer = new Timer(DELAY, new ActionListener(){
      @Override
      public void actionPerformed(ActionEvent e){
        object.evaluatePosition();
        repaint();
      }
    });
    timer.start();
  }
}

@Override
public void paintComponent(Graphics g){
  super.paintComponent(g);
  Graphics2D g2 = (Graphics2D)g;
  g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  g.drawOval((int)object.getPosition().getX(), (int)object.getPosition.getY()
     (int)object.getShape().getWidth(), object.getShape().getHeight());
}
此代码适用于DELAY=1000,但不适用于DELAY=100或DELAY=10,依此类推。我在这里读了一些示例代码,但它们对我来说都像我已经做过的那样。那么为什么我的代码不起作用呢

编辑(2016-01-30): 因为这似乎真的是一个性能问题,下面是MovableObject的代码(我只是认为这无关紧要,您可能会看到原因):


我的移动方式不是改变位置而是改变速度。请注意,我刚刚将shape对象从shape更改为Ellipse2D,以测试我的代码是否因为附加代码而出现性能问题。如果你认为这比它需要的更复杂:我实际上想增加一些复杂性,这样MovableObject就可以拥有任何shape子类的形状。我见过很多对我来说更复杂、渲染速度更快的代码。所以我想知道这有什么问题(除了它对于仅仅渲染椭圆来说有点太复杂之外)。

好的,这是一个简单的示例,基于您留下的上下文外代码片段,它似乎没有任何问题。它有一个简单的滑块控制的可变速度

导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.FontMetrics;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Point;
导入java.awt.RenderingHints;
导入java.awt.Shape;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.geom.AffineTransform;
导入java.awt.geom.Ellipse2D;
导入java.awt.geom.GeneralPath;
导入java.awt.geom.PathIterator;
导入java.util.Random;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JSlider;
导入javax.swing.Timer;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.event.ChangeEvent;
导入javax.swing.event.ChangeListener;
公共类显示扩展了JPanel{
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(新显示());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
私有MovableObject对象=新的MovableObject(新的Ellipse2D.Double(5,5,50,50));
专用int延迟=40;
私有计时器=新计时器(40,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
evaluatePosition(getSize());
重新油漆();
}
});
私有JSlider滑块=新JSlider(51000);
公开展览(){
对象。移动(50,50);
滑块=新的JSlider(51000);
slider.setSnapToTicks(真);
滑块。设置MajortickSpacing(10);
滑块。设置MinortickSpacing(5);
setLayout(新的BorderLayout());
添加(滑块,BorderLayout.SOUTH);
//这只是为了在
//更改侦听器和更新发生的时间、意图
//就是阻止它暂停“主”计时器。。。
计时器延迟=新计时器(250,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
如果(计时器!=null){
timer.stop();
}
timer.setDelay(slider.getValue());
timer.start();
}
});
slider.addChangeListener(新的ChangeListener(){
@凌驾
公共无效状态已更改(更改事件e){
delay.restart();
重新油漆();
}
});
滑块设置值(40);
}
@凌驾
公共维度getPreferredSize(){
返回新维度(200200);
}
@凌驾
公共组件(图形g){
超级组件(g);
Graphics2D g2=(Graphics2D)g.create();
g2.setRenderingHint(renderingHits.KEY\u ANTIALIASING,renderingHits.VALUE\u ANTIALIAS\u ON);
g2.draw(object.getTranslatedShape());
FontMetrics fm=g2.getFontMetrics();
字符串text=Integer.toString(slider.getValue());
g2.字符串(文本,0,fm.getAscent());
g2.dispose();
}
公共类可移动对象{
私人造型;
专用点位置;
西德尔塔私人酒店;
公共可移动对象(形状){
这个形状=形状;
位置=shape.getBounds().getLocation();
随机rnd=新随机();
xDelta=rnd.nextInt(8);
yDelta=rnd.nextInt(8);
if(rnd.nextBoolean()){
xDelta*=-1;
}
if(rnd.nextBoolean()){
yDelta*=-1;
}
}
公共无效移动(整数x,整数y){
位置。设置位置(x,y);
}
公共空间评估
public class MovableObject {
  // I would really like to use Shape instead of Ellipse2D so that 
  // objects of any shape can be created
  private Ellipse2D.Double shape; 
  private Point position;
  // Vector is my own class. I want to have some easy vector addition and
  // multiplication and magnitude methods
  private Vector velocity = new Vector(0, 0);
  private Vector acceleration = new Vector(0, 0); 
  private Date lastEvaluation = new Date();

  public MovableObject(Ellipse2D.Double objectShape){
    shape = objectShape;
  }

  public void evaluatePosition(){
    Date currentTime = new Date();
    long deltaTInS = (currentTime.getTime()-lastEvaluation.getTime())/1000;
    // s = s_0 + v*t + 0.5*a*t^2
    position = new Point((int)position.getX()+ (int)(velocity.getX()*deltaTInS) + (int)(0.5*acceleration.getX()*deltaTInS*deltaTInS),
                        (int)position.getY()+ (int)(velocity.getY()*deltaTInS) + (int)(0.5*acceleration.getY()*deltaTInS*deltaTInS));
    lastEvaluation = currentTime;
  }
}

public void move(Vector vector){
    velocity = velocity.add(vector);
    evaluatePosition(); 
}

public Point getPosition(){
    return position;
}

public Ellipse2D.Double getShape(){
    return shape;
}
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class Display extends JPanel {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new Display());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private MovableObject object = new MovableObject(new Ellipse2D.Double(5, 5, 50, 50));
    private int delay = 40;

    private Timer timer = new Timer(40, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            object.evaluatePosition(getSize());
            repaint();
        }
    });

    private JSlider slider = new JSlider(5, 1000);

    public Display() {
        object.move(50, 50);

        slider = new JSlider(5, 1000);
        slider.setSnapToTicks(true);
        slider.setMajorTickSpacing(10);
        slider.setMinorTickSpacing(5);
        setLayout(new BorderLayout());
        add(slider, BorderLayout.SOUTH);

        // This is simply designed to put an artificate delay between the
        // change listener and the time the update takes place, the intention
        // is to stop it from pausing the "main" timer...
        Timer delay = new Timer(250, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (timer != null) {
                    timer.stop();
                }
                timer.setDelay(slider.getValue());
                timer.start();
            }
        });

        slider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                delay.restart();
                repaint();
            }
        });

        slider.setValue(40);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.draw(object.getTranslatedShape());
        FontMetrics fm = g2.getFontMetrics();
        String text = Integer.toString(slider.getValue());
        g2.drawString(text, 0, fm.getAscent());
        g2.dispose();
    }

    public class MovableObject {

        private Shape shape;
        private Point location;

        private int xDelta, yDelta;

        public MovableObject(Shape shape) {
            this.shape = shape;
            location = shape.getBounds().getLocation();
            Random rnd = new Random();
            xDelta = rnd.nextInt(8);
            yDelta = rnd.nextInt(8);

            if (rnd.nextBoolean()) {
                xDelta *= -1;
            }
            if (rnd.nextBoolean()) {
                yDelta *= -1;
            }
        }

        public void move(int x, int y) {
            location.setLocation(x, y);
        }

        public void evaluatePosition(Dimension bounds) {
            int x = location.x + xDelta;
            int y = location.y + yDelta;

            if (x < 0) {
                x = 0;
                xDelta *= -1;
            } else if (x + shape.getBounds().width > bounds.width) {
                x = bounds.width - shape.getBounds().width;
                xDelta *= -1;
            }
            if (y < 0) {
                y = 0;
                yDelta *= -1;
            } else if (y + shape.getBounds().height > bounds.height) {
                y = bounds.height - shape.getBounds().height;
                yDelta *= -1;
            }

            location.setLocation(x, y);
        }

        public Shape getTranslatedShape() {
            PathIterator pi = shape.getPathIterator(AffineTransform.getTranslateInstance(location.x, location.y));
            GeneralPath path = new GeneralPath();
            path.append(pi, true);
            return path;
        }

    }
}