Java 间隔后在Swing JComponent中重新绘制

Java 间隔后在Swing JComponent中重新绘制,java,swing,timer,repaint,graphics2d,Java,Swing,Timer,Repaint,Graphics2d,我被分配了一个项目,我必须使用java中的GregorianCalendar对象制作一个模拟时钟。首先,我们被告知让时钟工作,以便它在每次运行时显示正确的时间。然后我们被告知让时钟每运行一秒就重新绘制一次。我创建了一个timer对象,并认为我可以添加一个ActionListener,并在每次调用actionPerformed时重新绘制它,但很明显,重新绘制不能以这种方式使用。这是我的密码: import javax.swing.*; import java.awt.event.*

我被分配了一个项目,我必须使用java中的GregorianCalendar对象制作一个模拟时钟。首先,我们被告知让时钟工作,以便它在每次运行时显示正确的时间。然后我们被告知让时钟每运行一秒就重新绘制一次。我创建了一个timer对象,并认为我可以添加一个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)));
        }
    }

有什么办法可以解决这个问题吗?也许我弄错了?

“使用Swing程序而不是重写
paint()
”,尽管正如您将看到的,这根本不是必需的。其次,你使用的是正确的。第三,为什么不简化自己,使用
JLabel
实例来显示时间呢?

您只需重写侦听器的构造函数:

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);
  • MyComponent应定义为MyFrame类中的类变量

  • 应该在MyFrame类中创建并启动计时器

  • 计时器的ActionListener应该在MyComponent变量上调用repaint

  • MyComponent类应该扩展JPanel,然后您可以调用super.paintComponent()作为第一条语句,在新时间绘制时钟之前清除面板


  • 嗯,你不是有一个向后的kemosabe吗?他应该重写paintComponent,而不是paint(如果他需要自定义绘制)?我可以用actionListener以这种方式重新绘制组件吗?@Tom:Swing定时器使用actionListener,所以是的,好的,使用actionListener来更改程序状态,然后在必要时调用repaint来触发重新绘制()。不过,我支持投票,只是修改了一个JLabel的文本,而不去麻烦定制绘画。@HovercraftFullOfEels,我说错了。