Java 摆动计时器的浮点值?
考虑以下摆动计时器:Java 摆动计时器的浮点值?,java,swing,graphics,timer,Java,Swing,Graphics,Timer,考虑以下摆动计时器: timer = new Timer (ballSpeed, tc); ballSpeed最初为10tc是一个动作侦听器类,它增加屏幕上绘制的对象的x值。变量ballSpeed有点用词不当,因为该值越低,对象移动越快 现在我希望对象的运动看起来尽可能平滑。因此,我将在ActionListener中逐个递增x值。也就是说,对象只能逐像素移动。我使用x++而不是x++=10。因此,我不会这样修改球的速度 既然Timer的第一个参数只接受一个整数,我就不能很好地控制对象的速度。我
timer = new Timer (ballSpeed, tc);
ballSpeed
最初为10tc
是一个动作侦听器类,它增加屏幕上绘制的对象的x值。变量ballSpeed
有点用词不当,因为该值越低,对象移动越快
现在我希望对象的运动看起来尽可能平滑。因此,我将在ActionListener中逐个递增x值。也就是说,对象只能逐像素移动。我使用x++
而不是x++=10
。因此,我不会这样修改球的速度
既然Timer
的第一个参数只接受一个整数,我就不能很好地控制对象的速度。我只能使用10、9、8等。对象要么移动太快,要么移动太慢
总而言之,毫秒精度是不够的
有办法解决这个问题吗?还是有更好的方法在屏幕上实现对象移动?A
javax.swing.Timer
没有足够的精度或精度来生成您试图实现的平滑图形。此外,回转计时器为:
其次,它的自动线程共享意味着您不必采取特殊步骤来避免产生太多线程。取而代之的是,计时器使用的线程与使光标闪烁、显示工具提示等的线程相同
如果您不想使用某些媒体框架或使用描述对象运动的API(而不是实际移动对象),则应使用swing计时器来安排下一次计算,但是,通过查看当前时间和上次计算期间的纳米时间之间的差异来确定自上次计算以来经过的时间
使用这种方法,在动力不足的机器上,您将有更多的Jagger但更正确的动画。A
javax.swing.Timer
没有足够的精度或精度来生成您试图实现的平滑图形。此外,回转计时器为:
其次,它的自动线程共享意味着您不必采取特殊步骤来避免产生太多线程。取而代之的是,计时器使用的线程与使光标闪烁、显示工具提示等的线程相同
如果您不想使用某些媒体框架或使用描述对象运动的API(而不是实际移动对象),则应使用swing计时器来安排下一次计算,但是,通过查看当前时间和上次计算期间的纳米时间之间的差异来确定自上次计算以来经过的时间
使用这种方法,在动力不足的机器上会有更多的Jagger但更正确的动画。好的,所以如果你真的想用纳秒,在这个答案的最后是一种使用ScheduledThreadPool的方法。但这纯粹是疯狂,这可能会导致大量问题,结果令人失望。我真的不会走那条路 使用50Hz(即每秒刷新50次),您应该能够获得理想的效果。问题是,我宁愿放弃这样的假设,你只能移动每像素的像素,并将你的球速度与你的移动速度联系起来 下面是一个示例(只需拖动滑块即可查看结果):
导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.net.MalformedURLException;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JSlider;
导入javax.swing.SwingUtilities;
导入javax.swing.Timer;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.event.ChangeEvent;
导入javax.swing.event.ChangeListener;
公共类测试2{
每秒图像的私有静态最终int NB_=50;
专用静态最终整数宽度=800;
专用静态最终内部高度=600;
私有静态最终int MIN=0;
专用静态最终整数最大值=100;
专用双速=转换(50);
私人双dx;
私人双重身份;
专用双x=宽度/2;
私人双y=高度/2;
私有JFrame;
专用电路板电路;
私人经营性工作;
private long lastMove=System.currentTimeMillis();
受保护的void initUI()引发错误的FormedUrlexception{
frame=newjframe(TestAnimation2.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(空);
圆圈=新的圆圈面板();
圆形。设置尺寸(20,20);
框架。添加(圆圈);
框架尺寸(宽度、高度);
dx=速度;
dy=速度;
最终JSlider滑块=新JSlider(最小、最大);
slider.addChangeListener(新的ChangeListener(){
@凌驾
公共无效状态已更改(更改事件e){
速度=转换(slider.getValue());
如果(dx>0){
dx=速度;
}否则{
dx=速度;
}
如果(dy>0){
dy=速度;
}否则{
dy=速度;
}
}
});
滑块设置值(50);
滑块。设置位置(0,0);
slider.setSize(slider.getPreferredSize());
frame.add(滑块);
frame.setVisible(true);
定时器t=新定时器(每秒1000个/NB\u个图像,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
move();
}
});
t、 start();
}
受保护的双转换(双滑动值){
返回sliderValue+1;
}
受保护的无效移动(){
x+=dx;
y+=dy;
如果(x+circle.getWidth()>frame.getContentPane().getWidth()){
x=frame.getConte
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestAnimation2 {
private static final int NB_OF_IMAGES_PER_SECOND = 50;
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
private static final int MIN = 0;
private static final int MAX = 100;
private double speed = convert(50);
private double dx;
private double dy;
private double x = WIDTH / 2;
private double y = HEIGHT / 2;
private JFrame frame;
private CirclePanel circle;
private Runnable job;
private long lastMove = System.currentTimeMillis();
protected void initUI() throws MalformedURLException {
frame = new JFrame(TestAnimation2.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
circle = new CirclePanel();
circle.setSize(20, 20);
frame.add(circle);
frame.setSize(WIDTH, HEIGHT);
dx = speed;
dy = speed;
final JSlider slider = new JSlider(MIN, MAX);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
speed = convert(slider.getValue());
if (dx > 0) {
dx = speed;
} else {
dx = -speed;
}
if (dy > 0) {
dy = speed;
} else {
dy = -speed;
}
}
});
slider.setValue(50);
slider.setLocation(0, 0);
slider.setSize(slider.getPreferredSize());
frame.add(slider);
frame.setVisible(true);
Timer t = new Timer(1000 / NB_OF_IMAGES_PER_SECOND, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
move();
}
});
t.start();
}
protected double convert(double sliderValue) {
return sliderValue + 1;
}
protected void move() {
x += dx;
y += dy;
if (x + circle.getWidth() > frame.getContentPane().getWidth()) {
x = frame.getContentPane().getWidth() - circle.getWidth();
dx = -speed;
} else if (x < 0) {
x = 0;
dx = speed;
}
if (y + circle.getHeight() > frame.getContentPane().getHeight()) {
y = frame.getContentPane().getHeight() - circle.getHeight();
dy = -speed;
} else if (y < 0) {
y = 0;
dy = speed;
}
circle.setLocation((int) x, (int) y);
circle.repaint();
}
public static class CirclePanel extends JPanel {
public CirclePanel() {
super();
setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillOval(0, 0, getWidth(), getHeight());
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
new TestAnimation2().initUI();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
}
import java.awt.Color;
import java.awt.Graphics;
import java.net.MalformedURLException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestAnimation2 {
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
private static final int SLOWEST_RATE = 10000000;
private static final int FASTEST_RATE = 1000;
private static final int RANGE = SLOWEST_RATE - FASTEST_RATE;
private static final int MIN = 0;
private static final int MAX = 100;
private double dx;
private double dy;
private double x = WIDTH / 2;
private double y = HEIGHT / 2;
private volatile long delay = convert(50);
private JFrame frame;
private CirclePanel circle;
private Runnable job;
private long lastMove = System.currentTimeMillis();
protected void initUI() throws MalformedURLException {
frame = new JFrame(TestAnimation2.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
circle = new CirclePanel();
circle.setSize(20, 20);
frame.add(circle);
frame.setSize(WIDTH, HEIGHT);
dx = 1;
dy = 1;
final ScheduledExecutorService sheduledThreadPool = Executors.newScheduledThreadPool(1);
final JSlider slider = new JSlider(MIN, MAX);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
delay = convert(slider.getValue());
}
});
slider.setValue(50);
slider.setLocation(0, 0);
slider.setSize(slider.getPreferredSize());
frame.add(slider);
frame.setVisible(true);
job = new Runnable() {
@Override
public void run() {
move();
sheduledThreadPool.schedule(job, delay, TimeUnit.NANOSECONDS);
}
};
sheduledThreadPool.schedule(job, delay, TimeUnit.NANOSECONDS);
}
protected long convert(float sliderValue) {
return (long) (SLOWEST_RATE - sliderValue / (MAX - MIN) * RANGE);
}
protected void move() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.err.println("Ellapsed " + (System.currentTimeMillis() - lastMove) + " delay is " + (double) delay / 1000000 + " ms");
x += dx;
y += dy;
if (x + circle.getWidth() > frame.getContentPane().getWidth()) {
x = frame.getContentPane().getWidth() - circle.getWidth();
dx = -1;
} else if (x < 0) {
x = 0;
dx = 1;
}
if (y + circle.getHeight() > frame.getContentPane().getHeight()) {
y = frame.getContentPane().getHeight() - circle.getHeight();
dy = -1;
} else if (y < 0) {
y = 0;
dy = 1;
}
circle.setLocation((int) x, (int) y);
frame.repaint();
lastMove = System.currentTimeMillis();
}
});
}
public static class CirclePanel extends JPanel {
public CirclePanel() {
super();
setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillOval(0, 0, getWidth(), getHeight());
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
new TestAnimation2().initUI();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}