[英]Java Thread.sleep/ Timer/ TimeUnit not working
我在我的一个有趣的小项目中遇到了一些麻烦:我想要实现的是在字符串输出之间延迟几秒钟,因此一次绘制一个字符(转换为字符串),以便给人一种输入它的错觉(在 JFrame 中)。 然而,它似乎是 for 循环(见下文),首先执行总增加的等待时间,然后一次绘制整个字符串,无论我使用哪种尝试过的解决方案( try and catch + Thread.sleep
、 TimeUnit
或java.swing.timer
和java.awt.timer
)。 这仍然是我在 Java 中的第一个项目之一,所以如果代码一团糟,我深表歉意。 到目前为止,stackoverflow 上现有的解决方案都没有帮助我。 编辑:错误消息(可能不相关)告诉我变量 n 应该声明为 final,因为它的范围不够。 这在这种情况下不起作用。
@Override
public void paintComponent(Graphics maler) {
super.paintComponent(maler);
maler.setColor(Color.WHITE);
maler.fillRect(0, 0, 600, 600);
maler.drawImage(bildchen, 37, 30, this);
maler.setColor(Color.BLACK);
maler.fillRect(0, 0, 600, 600);
maler.setColor(new Color(32, 194, 14));
Font kram = new Font("OCR A Extended", Font.BOLD, 40);
maler.setFont(kram);
String text = "WILLKOMMEN!";
final int n = 0;
int p = 90;
for (int i= 0; i<=10; i++) {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
maler.drawString(Character.toString(text.charAt(n)), p, 200);
}
};
timer.scheduleAtFixedRate(task, 1000, 1000);
p = p+34;
n++;
}
在这个工作部分中仍然存在的问题是 a) 每个字符都显示在同一个位置而不是增加 x 值; b) 某些字符被跳过(或在它们以三个成对出现之前)。 这是代码:
AtomicInteger animationState = new AtomicInteger(0);
@Override
public void paintComponent(Graphics maler) {
super.paintComponent(maler);
maler.setColor(Color.WHITE);
maler.fillRect(0, 0, 600, 600);
maler.drawImage(bildchen, 37, 30, this);
maler.setColor(Color.BLACK);
maler.fillRect(0, 0, 600, 600);
maler.setColor(new Color(32, 194, 14));
Font kram = new Font("OCR A Extended", Font.BOLD, 40);
maler.setFont(kram);
int p = 90;
String text = "WILLKOMMEN!";
maler.drawString(Character.toString(text.charAt(animationState.get())), p, 200);
runAnimation();
}
Timer timer = new Timer();
void runAnimation() {
TimerTask task = new TimerTask() {
public void run() {
if (animationState.get(
) < 11) {
animationState.incrementAndGet();
repaint();
} else {
cancel();
}
}
};
timer.scheduleAtFixedRate(task, 500, 500);
}
不幸的是,您尝试制作动画的方式从根本上是错误的。
正确的动画制作方式,需要通过某种方式存储动画的当前状态,让paintComponent
在绘制动画时使用动画的状态。
在这种情况下,您只对文本 WILLKOMMEN 的外观进行动画处理,因此您需要的状态只是一个数字:应该绘制多少个字母。 一个AtomicInteger
对象很适合这个,所以添加一个AtomicInteger
实例变量,并从paintComponent 中使用它:
AtomicInteger animationState = new AtomicInteger(0);
@Override
protected void paintComponent(Graphics maler) {
super.paintComponent(maler);
String text = "WILLKOMMEN!";
int p = 90;
maler.drawString(text.substring(0, animationState.get()), p, 200);
}
要真正使组件动画化,您需要定期更改动画状态并使组件重新绘制自身。 这可以从计时器线程完成。 在这种情况下,您可以调用incrementAndGet
方法将 animationState 更改为 animationState + 1,然后调用repaint()
方法显示更新状态。
Timer timer = new Timer();
void runAnimation() {
TimerTask task = new TimerTask() {
public void run() {
if (animationState.get() < 10) {
animationState.incrementAndGet();
repaint();
} else {
cancel();
}
}
};
timer.scheduleAtFixedRate(task, 1000, 1000);
}
当您希望动画开始时,您可以调用runAnimation
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.