间隔一段时间后在 Swing JComponent 中重新绘制

发布于 2024-12-05 19:16:13 字数 3300 浏览 1 评论 0原文

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

关于如何解决这个问题有什么想法吗?也许我的做法是错误的?

I have been assigned a project where I have to make an analog clock using the GregorianCalendar object in java. First, we were told to get the clock working, so that it shows the proper time on each run. Then we were told to make the clock redraw for every second that it is running. I made a timer object and thought I could add an ActionListener and have it repaint every time actionPerformed was invoked, but repaint obviously can't be used in this way. Here's my code:

    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)));
        }
    }

Any ideas on how to get around this? Maybe I'm going about it wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

嘿咻 2024-12-12 19:16:13

“Swing 程序应该覆盖paintComponent()而不是重写 paint(),”尽管您将看到,这根本没有必要。其次,您使用 是正确的javax.swing.Timer。第三,为什么不让自己变得简单并使用 JLabel 实例来显示时间呢?

"Swing programs should override paintComponent() instead of overriding paint()," although as you will see, this is not necessary at all. Second of all, you're right in using javax.swing.Timer. Third of all, why don't you make it easy on yourself and use a JLabel instance to display the time instead?

感情洁癖 2024-12-12 19:16:13
  1. MyComponent 应定义为 MyFrame 类中的类变量

  2. 应在 MyFrame 类中创建并启动计时器。

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

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

  1. MyComponent should be defined as a class variable in your MyFrame class

  2. The Timer should be created and started in your MyFrame class.

  3. The ActionListener for the Timer should invoke repaint on your MyComponent variable.

  4. Your MyComponent class should extend JPanel, then you can just invoke super.paintComponent() as the first statement to clear the panel before drawing the clock at its new time.

心碎的声音 2024-12-12 19:16:13

您只需重写 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);

You just override constructor of 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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文