我有一个小问题,但我不知道要解决它。我创建了简单的Applet,其中应该是简单的数字时钟。我正确地创建了所有方法,但重绘方法不会重新绘制我的applet。你能检查我的代码并说出错误的地方吗?感谢。
public class DigitalClock extends JApplet implements Runnable {
private Thread timeThread;
Date date = new Date();
public void start() {
timeThread = new Thread(this, "Clock");
timeThread.start();
}
@Override
public void stop() {
if (timeThread == null) {
return;
}
timeThread = null;
}
@Override
public void run() {
while (timeThread != null) {
repaint();
try {
timeThread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
@Override
public void paint(Graphics g) {
date.setTime(System.currentTimeMillis());
g.drawString(date.toString(), 50, 95);
}
}
答案 0 :(得分:5)
只需使用javax.swing.Timer
即可。 See how to use Swing Timer
这是一个例子。但是,不是在你正在做的JApplet
这样的顶级容器上绘画,而是在JPanel
上绘画,这是更推荐的
import java.awt.*;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;
public class TimerPanel extends JPanel {
private String dateString;
private final SimpleDateFormat format;
private final Font font;
private final Date date;
public TimerPanel() {
format = new SimpleDateFormat("hh:mm:ss a");
font = new Font("impact", Font.PLAIN, 30);
date = new Date();
date.setTime(System.currentTimeMillis());
dateString = format.format(date);
Timer timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
date.setTime(System.currentTimeMillis());
dateString = format.format(date);
repaint();
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(font);
FontMetrics fm = g.getFontMetrics(font);
int width = fm.stringWidth(dateString);
int height = fm.getAscent();
int x = getWidth() / 2 - width / 2;
int y = getHeight() / 2 + height / 2;
g.drawString(dateString, x, y);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 100);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TimerPanel timer = new TimerPanel();
JOptionPane.showMessageDialog(
null, timer, "Digital Clock", JOptionPane.PLAIN_MESSAGE);
}
});
}
}
更直接地回答您的问题,我的代码在我测试时有效,您唯一忘记的就是致电super.paint()
。这样做后按预期工作
@Override
public void paint(Graphics g) {
super.paint(g);
但是你想要避免使用Thread.sleep
。您可能会注意到这会导致闪烁。最好使用javax.swing.Timer
。这就是为什么我先回答我的例子。
答案 1 :(得分:1)
看看另一个例子。正如@peeskillet回答,我还使用JPanel
来显示时间,但在我的代码中,我使用JLabel
来显示时间。
public class ClockPane extends JPanel {
private JLabel clock;
public ClockPane() {
setLayout(new BorderLayout());
clock = new JLabel();
clock.setHorizontalAlignment(JLabel.CENTER);
clock.setFont(UIManager.getFont("Label.font").deriveFont(Font.BOLD, 32f));
tickTock();
add(clock);
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tickTock();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.setInitialDelay(0);
timer.start();
}
public void tickTock() {
clock.setText(DateFormat.getDateTimeInstance().format(new Date()));
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ClockPane clock = new ClockPane();
JOptionPane.showMessageDialog(
null, clock, "Digital Clock", JOptionPane.PLAIN_MESSAGE);
}
});
}
}
答案 2 :(得分:0)
您应该使用像
这样的私有属性private boolean running = true;
您将其设置为停止方法false
。在run-method中,您将其评估为停止条件,而不是评估timeThread != null
。此过程更安全,因为否则会导致NullPointerException
导致的run-method内的并发问题。
您应该通过在浏览器插件中观看其控制台输出来检查applet状态。你看到例外吗?