我正在尝试在java中实现一个简单的模拟时钟。我的时钟成功显示了我第一次运行程序的时间,但是在打开时,时间保持不变,没有任何绘图更新并冻结。我不明白为什么它不工作,我已经通过论坛试图寻找有类似问题的人,但不能。如果有人能找到我错的地方,我将非常感谢,谢谢
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing. JPanel;
public class ClockFace extends JPanel {
Date date = new Date();
private BufferedImage clockFace;
public ClockFace() {
this.init();
this.startClock();
}
private void init() {
JFrame window = new JFrame("Clock");
window.setContentPane(this);
this.setPreferredSize(new Dimension(600,600));
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setLocationRelativeTo(null);
}
//Draws the image to the ClockFace panel
public void paintComponent(Graphics g) {
Graphics2D twoD = (Graphics2D) g;
twoD.drawImage(clockFace, 0, 0, null);
}
public void startClock() {
while(true) {
int seconds = date.getSeconds();
int minutes = date.getMinutes();
int hours = date.getHours();
clockFace = new BufferedImage(600,600,BufferedImage.TYPE_INT_ARGB);
Graphics2D twoD = clockFace.createGraphics();
twoD.setColor(Color.BLACK);
twoD.fillRect(0, 0, 600, 600);
twoD.setColor(Color.WHITE);
twoD.translate(300,300);
//Drawing the hour markers
for(int i=0; i<12; i++) {
twoD.drawLine(0, -260, 0, -300);
twoD.rotate(Math.PI/6);
}
twoD.rotate(seconds*Math.PI/30);
twoD.drawLine(0, 0, 0, -290);
twoD.rotate(2*Math.PI-seconds*Math.PI/30);
twoD.rotate(minutes*Math.PI/30);
twoD.setStroke(new BasicStroke(3));
twoD.drawLine(0, 0, 0, -250);
twoD.rotate(2*Math.PI-minutes*Math.PI/30);
twoD.rotate(hours*Math.PI/6);
twoD.setStroke(new BasicStroke(6));
twoD.drawLine(0, 0, 0, -200);
repaint();
//Pausing until the next "tick"
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
答案 0 :(得分:5)
您正在阻止事件调度线程,阻止它处理任何新输入事件或处理任何新的绘制事件
有关详细信息,请参阅Concurrency in Swing。
所以不是......
public void startClock() {
while(true) {
//...
}
}
你应该使用更像......的东西。
public void startClock() {
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
//... Update time and schedule repaint
}
}
}
有关详细信息,请参阅How to Use Swing Timers
你也会发现这......
//Draws the image to the ClockFace panel
public void paintComponent(Graphics g) {
Graphics2D twoD = (Graphics2D) g;
twoD.drawImage(clockFace, 0, 0, null);
}
给你问题(绘画人工制品)。它应该是......
//Draws the image to the ClockFace panel
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D twoD = (Graphics2D) g;
twoD.drawImage(clockFace, 0, 0, null);
}
在天气方面已经(太多)讨论了核心问题与可能阻止事件调度线程或Date
类的非可变性质有关。
事实是,可能两者兼而有之。
java.util.Date
是某个时间点(创建时)的快照,它不会更改,也不会更新。因此,根据您的示例,您必须在循环的每次迭代中更新date
实例。
更好的解决方案可能是使用java.time.LocalTime
,除了更新,它通常更易于使用(恕我直言)
例如......
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.time.LocalTime;
import java.time.temporal.TemporalField;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 ClockFace());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ClockFace extends JPanel {
public ClockFace() {
this.startClock();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
LocalTime now = LocalTime.now();
int seconds = now.getSecond();
int minutes = now.getMinute();
int hours = now.getHour();
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, 600, 600);
g2d.setColor(Color.WHITE);
g2d.translate(300, 300);
//Drawing the hour markers
for (int i = 0; i < 12; i++) {
g2d.drawLine(0, -260, 0, -300);
g2d.rotate(Math.PI / 6);
}
g2d.rotate(seconds * Math.PI / 30);
g2d.drawLine(0, 0, 0, -290);
g2d.rotate(2 * Math.PI - seconds * Math.PI / 30);
g2d.rotate(minutes * Math.PI / 30);
g2d.setStroke(new BasicStroke(3));
g2d.drawLine(0, 0, 0, -250);
g2d.rotate(2 * Math.PI - minutes * Math.PI / 30);
g2d.rotate(hours * Math.PI / 6);
g2d.setStroke(new BasicStroke(6));
g2d.drawLine(0, 0, 0, -200);
g2d.dispose();
}
public void startClock() {
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();
}
}
}
答案 1 :(得分:1)
在while(true)之后插入{{1}}的计算。
这不是编写程序执行以时间增量计划的任务的方法。它只能解决你的问题。请参阅其他答案。