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