我被分配了一个项目,我必须使用java中的GregorianCalendar对象制作模拟时钟。首先,我们被告知让时钟工作,以便在每次运行时显示正确的时间。然后我们被告知要在每秒运行时重绘时钟。我创建了一个计时器对象,并认为我可以添加一个ActionListener并在每次调用actionPerformed时重新绘制它,但显然不能以这种方式使用重绘。这是我的代码:
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.*;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Date;
import javax.swing.Timer;
import java.lang.Math;
public class SwingClock {
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
MyFrame frame = new MyFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener listener = new TimePrinter();
Timer t = new Timer(1000, listener);
GregorianCalendar calendar = new GregorianCalendar();
t.start();
frame.setVisible(true);
}
});
}
}
class TimePrinter implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
//I'd like to repaint here every second, but I can't
}
}
class MyFrame extends JFrame
{
public MyFrame()
{
setTitle("Swing Clock");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
MyComponent component = new MyComponent();
add(component);
}
public static final int DEFAULT_WIDTH = 500;
public static final int DEFAULT_HEIGHT = 500;
}
class MyComponent extends JComponent
{
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
int leftX = 50, topY = 50, width = 300, height = 300;
Rectangle2D rect = new Rectangle2D.Double(leftX, topY, width, height);
Ellipse2D clockFace = new Ellipse2D.Double();
clockFace.setFrame(rect);
g2.draw(clockFace);
double centerX = clockFace.getCenterX();
double centerY = clockFace.getCenterY();
GregorianCalendar calendar = new GregorianCalendar();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
double minusMinute = (90 - (minute*6))*(Math.PI/180);
double minuteCosine = Math.cos(minusMinute);
double minuteSine = Math.sin(minusMinute);
double minusSecond = (90 - (second*6))*(Math.PI/180);
double secondCosine = Math.cos(minusSecond);
double secondSine = Math.sin(minusSecond);
double hourTheta = (90-(hour+(minute/60)*30))*(Math.PI/180);
g2.draw(new Line2D.Double(centerX,centerY,centerX+50*(Math.cos(hourTheta)),
centerY - 50*(Math.sin(hourTheta))));
g2.draw(new Line2D.Double(centerX,centerY,centerX+150*(minuteCosine),centerY-150*(minuteSine)));
g2.draw(new Line2D.Double(centerX, centerY, centerX+100*secondCosine,
centerY-100*(secondSine)));
}
}
有关如何解决此问题的任何想法?也许我错了?
答案 0 :(得分:5)
“摆动程序should override paintComponent()
而不是覆盖paint()
,”但正如您将看到的,这根本不是必需的。其次,你正确使用javax.swing.Timer
。第三,为什么不让自己轻松自如并使用JLabel
实例显示时间呢?
答案 1 :(得分:2)
MyComponent应定义为MyFrame类中的类变量
应在MyFrame类中创建并启动Timer。
Timer的ActionListener应该在MyComponent变量上调用重绘。
你的MyComponent类应该扩展JPanel,然后你可以调用super.paintComponent()作为清除面板的第一个语句,然后再在新的时间绘制时钟。
答案 2 :(得分:0)
您只需覆盖Listener的构造函数:
class TimePrinter implements ActionListener
{
private MyFrame frame;
TimePrinter(MyFrame frame){
this.frame=frame;
}
public void actionPerformed(ActionEvent event)
{
frame.repaint();
}
}
MyFrame frame = new MyFrame();
ActionListener listener = new TimePrinter(frame);