间隔后重新绘制Swing JComponent

时间:2011-09-21 18:22:04

标签: java swing timer repaint graphics2d

我被分配了一个项目,我必须使用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)));
        }
    }

有关如何解决此问题的任何想法?也许我错了?

3 个答案:

答案 0 :(得分:5)

“摆动程序should override paintComponent()而不是覆盖paint(),”但正如您将看到的,这根本不是必需的。其次,你正确使用javax.swing.Timer。第三,为什么不让自己轻松自如并使用JLabel实例显示时间呢?

答案 1 :(得分:2)

  1. MyComponent应定义为MyFrame类中的类变量

  2. 应在MyFrame类中创建并启动Timer。

  3. Timer的ActionListener应该在MyComponent变量上调用重绘。

  4. 你的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);