Java模拟时钟

时间:2018-04-09 19:22:42

标签: java swing time graphics clock

我正在尝试在java中实现一个简单的模拟时钟。我的时钟成功显示了我第一次运行程序的时间,但是在打开时,时间保持不变,没有任何绘图更新并冻结。我不明白为什么它不工作,我已经通过论坛试图寻找有类似问题的人,但不能。如果有人能找到我错的地方,我将非常感谢,谢谢

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing. JPanel;

public class ClockFace extends JPanel {

Date date = new Date();

private BufferedImage clockFace;

public ClockFace() {

    this.init();
    this.startClock();

}

private void init() {

    JFrame window = new JFrame("Clock");
    window.setContentPane(this);

    this.setPreferredSize(new Dimension(600,600));

    window.pack();
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setVisible(true);
    window.setLocationRelativeTo(null);

}

//Draws the image to the ClockFace panel
public void paintComponent(Graphics g) {

    Graphics2D twoD = (Graphics2D) g;
    twoD.drawImage(clockFace, 0, 0, null);

}

public void startClock() {

    while(true) {

        int seconds = date.getSeconds();
        int minutes = date.getMinutes();
        int hours = date.getHours();

        clockFace = new BufferedImage(600,600,BufferedImage.TYPE_INT_ARGB);
        Graphics2D twoD = clockFace.createGraphics();
        twoD.setColor(Color.BLACK);
        twoD.fillRect(0, 0, 600, 600);
        twoD.setColor(Color.WHITE);
        twoD.translate(300,300);

        //Drawing the hour markers
        for(int i=0; i<12; i++) {

            twoD.drawLine(0, -260, 0, -300);
            twoD.rotate(Math.PI/6);

        }

        twoD.rotate(seconds*Math.PI/30);
        twoD.drawLine(0, 0, 0, -290);

        twoD.rotate(2*Math.PI-seconds*Math.PI/30);
        twoD.rotate(minutes*Math.PI/30);
        twoD.setStroke(new BasicStroke(3));
        twoD.drawLine(0, 0, 0, -250);

        twoD.rotate(2*Math.PI-minutes*Math.PI/30);
        twoD.rotate(hours*Math.PI/6);
        twoD.setStroke(new BasicStroke(6));
        twoD.drawLine(0, 0, 0, -200);

        repaint();

        //Pausing until the next "tick"
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}

}

2 个答案:

答案 0 :(得分:5)

您正在阻止事件调度线程,阻止它处理任何新输入事件或处理任何新的绘制事件

有关详细信息,请参阅Concurrency in Swing

所以不是......

public void startClock() {
    while(true) {
       //...
    }
}

你应该使用更像......的东西。

public void startClock() {
    Timer timer = new Timer(500, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent evt) {
            //... Update time and schedule repaint
        }
    }
}

有关详细信息,请参阅How to Use Swing Timers

你也会发现这......

//Draws the image to the ClockFace panel
public void paintComponent(Graphics g) {

    Graphics2D twoD = (Graphics2D) g;
    twoD.drawImage(clockFace, 0, 0, null);

}

给你问题(绘画人工制品)。它应该是......

//Draws the image to the ClockFace panel
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D twoD = (Graphics2D) g;
    twoD.drawImage(clockFace, 0, 0, null);

}

更新...

在天气方面已经(太多)讨论了核心问题与可能阻止事件调度线程或Date类的非可变性质有关。

事实是,可能两者兼而有之。

java.util.Date是某个时间点(创建时)的快照,它不会更改,也不会更新。因此,根据您的示例,您必须在循环的每次迭代中更新date实例。

更好的解决方案可能是使用java.time.LocalTime,除了更新,它通常更易于使用(恕我直言)

例如......

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.time.LocalTime;
import java.time.temporal.TemporalField;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new ClockFace());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ClockFace extends JPanel {

        public ClockFace() {
            this.startClock();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 600);
        }

        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g.create();

            LocalTime now = LocalTime.now();
            int seconds = now.getSecond();
            int minutes = now.getMinute();
            int hours = now.getHour();

            g2d.setColor(Color.BLACK);
            g2d.fillRect(0, 0, 600, 600);
            g2d.setColor(Color.WHITE);
            g2d.translate(300, 300);

            //Drawing the hour markers
            for (int i = 0; i < 12; i++) {

                g2d.drawLine(0, -260, 0, -300);
                g2d.rotate(Math.PI / 6);

            }

            g2d.rotate(seconds * Math.PI / 30);
            g2d.drawLine(0, 0, 0, -290);

            g2d.rotate(2 * Math.PI - seconds * Math.PI / 30);
            g2d.rotate(minutes * Math.PI / 30);
            g2d.setStroke(new BasicStroke(3));
            g2d.drawLine(0, 0, 0, -250);

            g2d.rotate(2 * Math.PI - minutes * Math.PI / 30);
            g2d.rotate(hours * Math.PI / 6);
            g2d.setStroke(new BasicStroke(6));
            g2d.drawLine(0, 0, 0, -200);

            g2d.dispose();
        }

        public void startClock() {
            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    repaint();
                }
            });
            timer.start();
        }

    }

}

答案 1 :(得分:1)

在while(true)之后插入{{1}}的计算。

这不是编写程序执行以时间增量计划的任务的方法。它只能解决你的问题。请参阅其他答案。