Java的简单数字时钟

Java的简单数字时钟

Java的简单数字时钟

这里是最简单的实现方法,大概思路就是在一个JComponent上每隔一段时间进行一次重绘,为了保证重绘Timer的执行时间和终了时间,重写JComponentaddNotify方法和removeNotify方法,最后在DigitalClockUI中重写paint方法来绘制界面,并且重写 getPreferredSize使绘制的内容自适应界面的大小.

先看看效果:



基本的工程目录如下:

首先是最基本的界面: Clock,在这个工程里,这个类作用很小,定义不定义其实都无所谓,这儿定义它主要是为了统一,为以后实现其它时钟提供方便

这儿把它定义成抽象的

/**

 * This bean to define basic properties and behaviors of a clock, concrete

 * instances will be implemented by <code>DigitalClock</code> and others.

 */

publicabstractclass Clock extends JComponent {

为它提供几个属性:

    /**

     * The calendar instance for this clock.

     */

    private Calendar calendar;

    /**

     * Background image of the clock.

     */

    private Image bgImage;

    /**

     * Font rendering context - assumes no default transform, anti-aliasing

     * active and fractional metrics allowed.

     */

publicstaticfinal FontRenderContext frc = new FontRenderContext(null, true, true);

其中FontRenderContext提供了文本显示和绘制的信息容器.

在构造函数中把calendar初始化:

    calendar = Calendar.getInstance();

接着看DigitalClock,这个类继承Clock,主要是提供时钟计时Timer启动和终止的,另外提供了数字时钟的页面分隔符信息,以及UI设置和取得.

首先是定义的属性:

    /**

     * divide time.

     */

    private String padding1 = "";

    private String padding2 = "";

分别代表时分秒之间的分隔和秒与毫秒之间的分隔.

接着是构造函数,提供基本的和带参数的两种:

    /**

     * Default construct: Uses default format and appearance.

     */

    public DigitalClock() {

       super();

       setFont(new Font("Arial", Font.BOLD, 20));

       setOpaque(true);

       padding1 = ":";

       padding2 = ".";

       setUI(DigitalClockUI.createUI(this));

    }

    /**

* Constructor: Initializes a digital-type clock by using given *parameters.

     */

    public DigitalClock(String padding1, String padding2, Font font,

           Color fg, Color bg, Locale locale) {

通过setUI(DigitalClockUI.createUI(this));把新的自定义UI赋给JComponent.

最后通过addNotifyremoveNotify方法复写启动和终止计时Timer

    /**

     * Invoked when panel is added to a container.

     */

    @Override

    publicvoid addNotify() {

       super.addNotify();

       getUI().start();

    }

    /**

     * Invoked when panel is removed from a container.

     */

    @Override

    publicvoid removeNotify() {

       getUI().stop();

       super.removeNotify();

    }

最后就是DigitalClockUI类了,它主要提供页面的绘制,计时Timer的管理和时间的计算以及界面大小的调整功能.

首先是继承关系:

publicclass DigitalClockUI extends PanelUI implements ActionListener {

它通过继承PanelUI(其实就是ComponentUI)实现时钟界面UI管理,实现ActionListener接口则是为了SwingTimer.

在构造函数中,Timer启动   

// stopwatch

       timer = new Timer(10, this);

仿照其他Component组件提供UI代理,使界面可以设置UI:

// Create an instance of the UI delegate for this component

    publicstatic ComponentUI createUI(DigitalClock component) {

       returnnew DigitalClockUI(component);

    }

然后定义类使用的属性:

    // Attributed string containing current time

    protected AttributedString timeString = null;

    // Text layout of attributed string

    protected TextLayout textLayout = null;

    // Attributed string containing current timezone.

    protected AttributedString timezoneString = null;

    // Text layout of attributed timezone.

    protected TextLayout textTimezoneLayout = null;

分别定义了绘制时间和时区的字符串属性格式和布局.

当组件加入到容器中呈现时,Timer启动,actionPerformed将会被调用.

    @Override

    publicvoid actionPerformed(ActionEvent event) {

在这个方法里,取得当前时间:

       // Create a new attributed string with the new time

       Date current = new Date();

       Calendar cal = panel.getCalendar();

       cal.setTime(current);

通过SimpleDateFormat类把时间格式化:

    // Hour24 mode

       df = new SimpleDateFormat("HH" + panel.getPadding1() + "mm"

              + panel.getPadding1() + "ss", panel.getLocale());

       // Draw AM/PM

       int tmpLen2 = 0;

       // mode

       df.applyPattern("a");

       // timezone

       df.applyPattern("Z");

       StringBuffer sb = new StringBuffer("GMT");

       sb.append(df.format(current));

       sb.insert(6, ":");

       df.applyPattern("zzzz");

然后将格式化好的时间字符串通过AttributedString设置显示格式:

timeString = new AttributedString(str);

// Render main time area

timeString.addAttribute(TextAttribute.FONT, font, 0, 6 + 2 * panel

              .getPadding1().length());

timeString.addAttribute(TextAttribute.FOREGROUND,panel.getForeground());

// Do blinking if reach alarm point

timeString.addAttribute(TextAttribute.FOREGROUND,

              panel.getForeground(), 0, 6 + 2 * panel.getPadding1().length());

// Render padding1, do blinking

timeString.addAttribute(TextAttribute.FOREGROUND, blink == 0 ? panel

              .getForeground() : panel.getBackground(), 2, 2 + panel

              .getPadding1().length());

timeString.addAttribute(TextAttribute.FOREGROUND, blink == 0 ? panel

              .getForeground() : panel.getBackground(), 2 + panel

              .getPadding1().length() + 2, 4 + 2 * panel.getPadding1()

              .length());

然后设置TextLayout

       // Create a new text layout and signal the panel that it needs

       // repainting

       textLayout = null;

       textLayout = new TextLayout(timeString.getIterator(), Clock.frc);

最后根据字符串大小设置组件大小,刷新

    // To keep the clock size fit for

       // actual size in time.

       panel.setSize(getPreferredSize(panel));

       panel.repaint();

       current = null;

       df = null;

最后一个方法是复写getPreferredSize使组件可以自适应大小

    // Return the preferred size for the component

    @Override

    public Dimension getPreferredSize(JComponent c) {

首先得出两个字符串大小:

Dimension size1 = textLayout.getBounds().getBounds().getSize();

Dimension size2 = textTimezoneLayout == null ? null : textTimezoneLayout.getBounds().getBounds().getSize();

然后宽度取2者大的,再额外增加一点Border

int max = width1;

       if (width2 > max)

           max = width2;

       size.width = max + MARGIN + 2;

高度选取2者之和加上两者间的间隙:

int height1 = (int) (textLayout.getAscent() + textLayout.getDescent() + textLayout.getLeading());

int height2 = (int) (textTimezoneLayout == null ? 0 : textTimezoneLayout.getAscent()+ textTimezoneLayout.getDescent() + textTimezoneLayout.getLeading());

size.height = (height1 + MARGIN) + (height2 + MARGIN);

到此为止,最简单的数字时钟就完成了.

通过

private DigitalClock getDigitalClock() {

    if (digitalClock == null) {

       // To create a digital-type clock with dark

       // red foreground and black background.

       digitalClock = new DigitalClock(":", "'", new Font("Comic Sans MS",Font.BOLD, 20), Color.GREEN.darker(), Color.BLACK

                  .brighter(), Locale.ENGLISH);

       }

       returndigitalClock;

    }

取得数字时钟组件,然后就和一般Java组件一样使用了.



你可能感兴趣的:(Java的简单数字时钟)