`
zeyuphoenix
  • 浏览: 55025 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java的指针时钟

 
阅读更多
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="ProgId" content="Word.Document"> <meta name="Generator" content="Microsoft Word 12"> <meta name="Originator" content="Microsoft Word 12"> <link rel="File-List" href="file:///C:%5CDOCUME%7E1%5Cphoenix%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"> <link rel="Edit-Time-Data" href="file:///C:%5CDOCUME%7E1%5Cphoenix%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_editdata.mso"> <!--[if !mso]> <style> v":* {behavior:url(#default#VML);} o":* {behavior:url(#default#VML);} w":* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><link rel="themeData" href="file:///C:%5CDOCUME%7E1%5Cphoenix%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"> <link rel="colorSchemeMapping" href="file:///C:%5CDOCUME%7E1%5Cphoenix%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"> <!--[if gte mso 9]><xml> Normal 0 false 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE </xml><![endif]--><!--[if gte mso 9]><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4;} @font-face {font-family:Calibri; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-alt:"Times New Roman";} @font-face {font-family:""@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal { mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Calibri","serif"; mso-bidi-font-family:"Times New Roman";} p.MsoHeader, li.MsoHeader, div.MsoHeader { mso-style-link:"页眉 Char"; margin:0cm; margin-bottom:.0001pt; text-align:center; tab-stops:center 207.65pt right 415.3pt; layout-grid-mode:char; border:none; padding:0cm; font-size:9.0pt; font-family:"Calibri","serif"; mso-bidi-font-family:"Times New Roman";} p.MsoFooter, li.MsoFooter, div.MsoFooter { mso-style-link:"页脚 Char"; margin:0cm; margin-bottom:.0001pt; tab-stops:center 207.65pt right 415.3pt; layout-grid-mode:char; font-size:9.0pt; font-family:"Calibri","serif"; mso-bidi-font-family:"Times New Roman";} p.MsoAcetate, li.MsoAcetate, div.MsoAcetate { mso-style-link:"批注框文本 Char"; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:9.0pt; font-family:"Calibri","serif"; mso-bidi-font-family:"Times New Roman";} span.Char {mso-style-name:"页眉 Char";} span.Char0 {mso-style-name:"页脚 Char";} span.Char1 {mso-style-name:"批注框文本 Char";} .MsoChpDefault { mso-bidi-font-family:"Times New Roman";} /* Page Definitions */ @page {} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; layout-grid:15.6pt;} div.Section1 {page:Section1;} --> </style> <!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.5pt; font-family:"Calibri","serif";} </style> <![endif]-->

Java的指针时钟最基础的原理和数字时钟其实差不多,也是利用SwingTimer计时,每隔一定时间重新绘制组件,最后重写paintComponent方法来更新界面.和之前介绍的时钟一样,为了保证时钟的正确启动和终止,需要重写组件的addNotifyremoveNotify方法,在方法内加入Timer的启动和终止;最后也要重写组件getPreferredSize方法使组件的大小自动适应.

首先看最终的效果:

 

<!--[if gte vml 1]> <![endif]-->

<!--[if gte vml 1]> <![endif]-->

工程的目录:




<!--[if gte vml 1]> <![endif]-->

其中timespinner包是时间的微调组件,这儿只是为了显示用的,和指针时钟无关,先不介绍了.

Clock包则是显示指针时钟的包,指针时钟的组件类是AnalogClock,它继承于Clock,处理和数字时钟的基本一致,先看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 {

属性也是:

    /**

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

     * active and fractional metrics allowed.

     */

    publicstaticfinal FontRenderContext frc = new FontRenderContext(null,

           true, true);

    /**

     * The calendar instance for this clock.

     */

    protected Calendar calendar;

    /**

     * @see #getBgImage()

     */

    protected Image bgImage;

和数字时钟完全一样,提供基本属性和文本显示和绘制的信息容器.

再看AnalogClock

/**

 * To implement a analog-type clock.

 */

publicclass AnalogClock extends Clock implements ActionListener {

它有两个属性:

    /**

     * Parts to construct this clock.

     */

    private Parts parts = null;

    /**

     * A timer to run in a independent thread.

     */

    private Timer timer = null;

一个是定时刷新时间的Timer,一个是时钟的样式.

具体方法有,

1.复写addNotifyremoveNotify方法控制Timer的启动和终止.

    /**

     * @see java.awt.Component#addNotify()

     */

    @Override

    publicvoid addNotify() {

       super.addNotify();

       timer.start();

    }

    /**

     * @see java.awt.Component#removeNotify()

     */

    @Override

    publicvoid removeNotify() {

       timer.stop();

       super.removeNotify();

    }

2.复写getPreferredSize方法使组件自动适应大小.

    /**

     */

    @Override

    public Dimension getPreferredSize() {

       Dimension size = getSize();

       size.width = parts.getSize().width;

       size.height = parts.getSize().height + MARGIN;

       return size;

    }

3.复写paintComponent使修正外观

    @Override

    publicvoid paintComponent(Graphics g) {

4.实现Timer必须的actionPerformed方法,做定时任务

    /**

     * Do transformation based on current precise time when display.

     */

    @Override

    publicvoid actionPerformed(ActionEvent e) {

主要操作是取得当前时间,更新组件:

       parts.doTransform(hour, minute, second, millisecond);

       repaint();

       // Resize this clock in time

       setSize(getPreferredSize());

还有最主要的构造函数,组件的外观通过它传入,

    /**

     * Constructor:<br>

     * Creates an analog-type clock by using given parts.

     */

    public AnalogClock(Parts parts) {

并且把Timer初始化:

timer = new Timer(1000, this);

到现在为止,和时间设置相关的已经完成,剩下的就是传入组件的表现Parts,使画面呈现了.

指针时钟的呈现主要使用了PartsRotatePartsBasicPartsMyParts四个类,它们是继承关系.

其中Parts是最基本的,它主要描绘指针时钟最外层的边框、指针时钟颜色和大小,,并且提供了虚的 doTransform方法供子类实现绘制;

RotatePartsParts的基础上提供了圆心和半径把数字时钟最外层的圆的属性提供出来,并提供了画刻度的方法,没有具体的绘制;

BasicParts是主要的绘制类,它完成了指针时钟显示的大部分工作,提供时钟上的数字和时分秒指针以及指针的变换器这些基本属性,并提供了绘制数字和指针在组件上的方法,简单的继承它就可以实现一个指针时钟了,只是不够美观;

MyParts是继承于BasicParts的类,它主要目的是把指针时钟做的更美观,并且定义时钟的基本大小,颜色等,提供了更好的绘制钟面上数字和指针的方法.

现在依次详细看看这些类:

首先是最基本的Parts

/**

 * To represent all modules which a analog-type clock consists of.

 */

publicabstractclass Parts extends JComponent {

再看看它的属性:

    /**

     * Coloring scheme for the parts.

     */

    protected BasicColor colors;

    /**

     * Size of this parts.

     */

    protected Dimension size;

    /**

     * Clock face.

     */

    protected Shape dial;

分别控制时钟的各个颜色,大小,和外观样式.

然后是方法,它提供一个虚方法给具体类实现:

    /**

     * Changes positions of hour hand, minute hand, second hand and         * decisecond hand based on current time.

     */

    publicabstractvoid doTransform(int hour, int minute, int second,

           int millisecond);

这个方法主要是按给定的时间值得出指针在时钟上的位置和角度.

接着是RotateParts类:

/**

  * This class defines a classical clock behavior by using rotation pattern, *as we all know in common sense.

 */

publicabstractclass RotateParts extends Parts {

再看看它的属性:

    /**

     * X coordinate of the center.

     */

    protectedfloatx;

    /**

     * Y coordinate of the center.

     */

    protectedfloaty;

    /**

     * Radius of the clock face.

     */

    protectedfloatradius;

分别给定了指针时钟的圆的圆心和半径,没有提供绘制方面的属性.

然后是方法,它提供了几个给定时间值换算为时钟位置的方法:

    /**

     * a rotation instance from 12 o'clock direction.

     */

    public AffineTransform getTransform() {

       return AffineTransform.getRotateInstance(0, x, y);

    }

这个方法是提供默认的指针的位置,即绕圆心(0,0)点旋转0,12点位置.

接着

    /**

     * Sets rotation algorithm by given value.

     */

    publicvoid setToRotation(AffineTransform af, double value, int grad) {

       af.setToRotation(value * (2 * Math.PI / grad), x, y);

    }

这个方法根据给定的具体值(这里可以理解为当前具体时间的时、分或者秒)和总的时间划分(12或者60)算出需要旋转的角度,然后绕圆心(x,y)旋转.

最后是

    /**

     * Gets a rotation transform by given parameters.

     */

    public AffineTransform getRotateInstance(int grad, int seq) {

       return getRotateInstance(x, y, grad, seq);

    }

    /**

     * Get a rotation transform by given parameters.

     */

    publicstatic AffineTransform getRotateInstance(float x, float y, int grad, int seq) {

return AffineTransform.getRotateInstance((2 * Math.PI / grad) * seq, x, y);

    }

这个是根据指定的值和总值以及中心点取得映射变换的实例.

接着就是重要的BasicParts类了

/**

 * To implement a classical analog-type clock face, except definitely *describing the hands shape.<br>

*/

publicabstractclass BasicParts extends RotateParts {

它是钟表刻度的继承,继承它就可以实现自己的指针钟表了.

先看它的属性:

    /**

     * Hour hand.

     */

    protected Shape hourHand;

    /**

     * Minute hand.

     */

    protected Shape minuteHand;

    /**

     * Second hand.

     */

    protected Shape secondHand;

    /**

     * Hour hand behavior controller.

     */

    protected AffineTransform hourTransform;

    /**

     * Minute hand behavior controller.

     */

    protected AffineTransform minuteTransform;

    /**

     * Second hand behavior controller.

     */

    protected AffineTransform secondTransform;

6个属性提供时分秒三个时针的形状和绘制映射类,通过它们可以对钟表进行绘制.

    /**

     * Moves all parts, to leave some margin.

     */

    protectedtransient AffineTransform trans;

这个属性是在对时分秒指针绘制时提供变换的.

    /**

     * Arabic time punctualities.

     */

    publicstaticfinal String[] ARABIC = { "12", "1", "2", "3", "4", "5", "6","7", "8", "9", "10", "11" };

    /**

     * Roman time punctualities.

     */

    publicstaticfinal String[] ROMAN = { "XII", "I", "II", "III", "IV", "V","VI", "VII", "VIII", "IX", "X", "XI" };

这两个常量是提供表盘的刻度显示的,也可以自己定义一个12位的数组代替.

再看它的构造函数

/**

* Constructor: Joins every parts in a entire analog-type clock.

*/

    protected BasicParts(Shape dial, Shape hourHand, Shape minuteHand,

           Shape secondHand, String[] numbers, BasicColor colors)

           throws Exception {

需要传入外围图形、时分秒图形、刻度数字和各部分颜色.当然可以传入new GeneralPath()

在以后再具体描绘它们.

    /**

     * Initializes hand transformation.

     */

    protectedvoid initTransform() {

       hourTransform = getTransform();

       minuteTransform = getTransform();

       secondTransform = getTransform();

    }

这个是初始化时分秒绘制映射类的.默认让它们都指向12点方向.

    /**

     * Default algorithm for hands's action trace.

     */

    @Override

    publicvoid doTransform(int hour, int minute, int second, int millisecond) {

       if (hourTransform != null && minuteTransform != null

              && secondTransform != null) {

           setToRotation(hourTransform,

                  hour + (minute + second / 60.0) / 60.0, 12);

           setToRotation(minuteTransform, minute + second / 60.0, 60);

           setToRotation(secondTransform, second, 60);

       }

    }

这个是父类的虚函数的实现,根据给定值旋转指定角度呈现给画面.

    /**

     * Draws a number at 12 o'clock.

     */

    protectedvoid drawNumber(Graphics g, String number, Font font) {

       BasicColor c = (BasicColor) colors;

       AttributedString num = new AttributedString(number);

       if (font != null) {

           num.addAttribute(TextAttribute.FONT, font);

       }

       drawNumber(g, num, x, y - radius, c.numbers);

    }

    /**

     * Draws a number at 12 o'clock.

     */

    publicstaticvoid drawNumber(Graphics g, AttributedString number, float x, float y, Color color) {

       if (number != null) {

           Graphics2D g2 = (Graphics2D) g;

           g2.setPaint(color);

           g2.drawString(number.getIterator(), x, y);

       }

    }

是按指定的属性在表盘上画刻度的.

最后是重要的paintComponent方法了

    @Override

    publicvoid paintComponent(Graphics g) {

它按照属性了上面取得的绘制映射类进行绘制

首先是绘制外围界面:

    g2.setPaint(c.dail);

    g2.fill(trans.createTransformedShape(dial));

    g2.setPaint(Color.BLACK);

g2.draw(trans.createTransformedShape(dial));

然后绘制时分秒指针:

// Draw hour hand

g2.setPaint(c.hourHand);

g2.fill(trans.createTransformedShape(hourTransform

                  .createTransformedShape(hourHand)));

分秒基本和时的一样.

最后要看的类就是自己实现的MyParts类了,其实这里简单实现一个SimpleParts也可以的只是界面比较难看,如下图:

<!--[if gte vml 1]> <![endif]-->

所以需要做漂亮点还是要自己去写一部分代码的.

先看继承关系

/**

 * A piece of sample code to show how to develop a nice-looking analog-type

 * clock by using this API.

*/

publicfinalclass MyParts extends BasicParts {

首先还是看它的属性:

    /**

     * Radius of the clock face.

     */

    protectedfloatradius;

这个是定义钟表的半径.

    /**

     * 12 hour ticks.

     */

    protected Shape tick;

    /**

     * Other 48 minute ticks not at time punctualities.

     */

    private GeneralPath smallTick;

2个是定义钟表的刻度,分别代表比较明显的12个整点刻度,和其它48个不明显的刻度.

    /**

     * X coordinate of left top corner.

     */

    privatestaticfloatxNW = 0;

    /**

     * Y coordinate of left top corner.

     */

    privatestaticfloatyNW = 0;

    /**

     * Width of the square.

     */

    privatestaticfloatwidth = 170;

2个属性分别代表距离中心的坐标和表的外围大小.

    /**

     * Additional margin size in proportion of radius by percentage.

     */

    privatestaticfloatmarginOfRadius = 0.1f;

这个属性代表空白区域的百分比.

然后是方法,先看画刻度的方法:

    /**

     * Draws ticks.

     */

    publicstaticvoid drawTicks(Graphics g, Shape tick, int tickNumber,

           float x, float y, AffineTransform trans, Color color) {

首先得到最基本的指针位置,默认指向12点位置:

AffineTransform at = AffineTransform.getRotateInstance(0, x, y);

然后取得偏移的角度:

at = RotateParts.getRotateInstance(x, y, tickNumber, p);

最后是绘制:

g2.fill(trans.createTransformedShape(at

              .createTransformedShape(tick)));

再看绘制指针的方法:

    /**

     * Generate hour hand and minute hand shape.

     */

    privatevoid createHand(Shape hand, float x, float y, float radius,

           float widthPercent, float lengthPercent, float marginPercent,

           float firstWidthPercent, float firstLengthPercent,

           float secondWidthPercent, float secondLengthPercent) {

这个是绘制时针和分针的,形状是尾部粗尖端细

h.moveTo(x, y);

h.curveTo(x - radius * (widthPercent / 2) * (firstWidthPercent / 2), y- radius * marginPercent * (firstLengthPercent / 2), x – radius * (widthPercent / 2) * (secondWidthPercent / 2), y – radius * marginPercent * (secondLengthPercent / 2), x, y – radius * lengthPercent);

    /**

     * Generates concrete hand shape.

     */

publicstaticvoid createHand(Shape hand, float x, float y, float radius, float widthPercent, float lengthPercent, float marginPercent) {

这个是绘制秒针的,粗细均匀,比较简单

h.moveTo(x - radius * (widthPercent / 2), y + radius * marginPercent);

h.lineTo(x + radius * (widthPercent / 2), y + radius * marginPercent);

再看绘制表上数字的方法

    /**

     * An algorithm to locate time punctualities numbers on a round clock *face

     */

 privatevoid drawNumbers(Graphics g, String[] numbers, float marginPercent, Font font) {

3点举例,先算角度:

float cZero1 = (float) Math.cos((2 * Math.PI / 12) * 3);

再把数字转为属性串,取得宽度:

num = new AttributedString(numbers[p]);

num.addAttribute(TextAttribute.FONT, font);

layout = new TextLayout(numbers[p], font, Clock.frc);

float width = layout.getBounds().getBounds().width;

然后算出坐标:

float px = (float) (x + trans.getTranslateX() + radius

                     * (1 + marginPercent) * sin);

最后调用父类绘制方法绘制:

super.drawNumber(g, num, px, py, color);

接着是初始化方法,它把指针和表盘大小,位置都进行了初始化:

    /**

     * To initialize some parameters and every parts shape.

     */

    protectedvoid initialize() {

首先算圆心和半径:

x = xNW + width / 2;

       y = yNW + width / 2;

       radius = width / 2 - 5;

然后画时针:

设定各个百分比位置,然后调用时针方法

float hWidthOfRadius = 0.08f;

float hLengthOfRadius = 0.7f;

createHand(hourHand, x, y, radius, hWidthOfRadius, hLengthOfRadius,

               hMarginOfRadius, fstWidthOfRadius, fstLengthOfRadius,

              sndWidthOfRadius, sndLengthOfRadius);

其它指针也是类似画出.

最后是复写paintComponent方法,当属性变更时重新绘制指针时钟:

    /**

     * Paint ticks and time punctualities.

     */

    @Override

    publicvoid paintComponent(Graphics g) {

在里面进行了指针数字和刻度绘制方法的调用

// Draw 12 numbers by using specific font

      drawNumbers(g, numbers, marginOfRadius, new Font("Ravie", Font.BOLD + Font.ITALIC, 8));

       // Draw 12 hour ticks, here use SimpleParts

       drawTicks(g, tick, max, x, y, trans, c.tick);

       // Draw 48 minute ticks, here use SimpleParts

       drawTicks(g, smallTick, 60, x, y, trans, c.tick);

这个绘制类就完成了.

到此为止,所有的指针时钟的创立工作全部完成.

最后通过

    /**

     * This method shows how to create a user defined analog-type clock

     */

    private AnalogClock getColorfulClock() {

       if (colorfulClock == null) {

           try {

              colorfulClock = new AnalogClock(new MyParts());

           } catch (Exception e) {

              e.printStackTrace();

           }

       }

       returncolorfulClock;

    }

就可以使用了.

分享到:
评论

相关推荐

    Java实现带指针的时钟

    本资源为使用Java开发的带有时针,分针,秒针的圆形时钟,同时还可以同步显示数字时间。时间使用获取的系统时间。

    java指针时钟

    Java编写的时钟程序,该时钟包含基本的时刻数字以及时针分针秒针,该代码完全正确,欢迎大家下载使用。

    java 实现绘制指针时钟 和多线程服务器

    java 实现绘制指针时钟 和多线程服务器java 实现绘制指针时钟 和多线程服务器java 实现绘制指针时钟 和多线程服务器java 实现绘制指针时钟 和多线程服务器java 实现绘制指针时钟 和多线程服务器java 实现绘制指针...

    基于java swing的指针时钟

    基于java的指针时钟,用的是swing组件,适合java初学者的算法研究

    java图形时钟基于自带多媒体编程

    基于eclipse的java图形时钟,用java自带的多媒体编程,时钟主体用的是一幅时钟图片,指针是基于awt类画的。同时采用 了双缓冲技术,消除了闪烁现象。

    java图形化编程基础,用java编写时钟钟面

    用java编写一个时钟钟面: 再不要求时钟动起来的情况下,只需用一些绘图的基础知识就行了,只需注意时钟钟面上的60个短线的绘制就OK了!

    设计一个动态时钟程序,指针

    本实验旨在通过实验,培养将JAVA 线程的相关知识点(包括线程调度,线程同步等)有机结合并加以综合应用,在实验中设计多线程程序的能力。...设计和编写一个编写一个指针式时钟程序,应用线程实现时钟的走动。

    java图形界面时钟

    稍微美化了一些的界面,看起来舒服多了,获取本机时间,在表盘上显示机械钟的运动状态,不过时针跳动的有点大,因为定义的是一小时走一步,可以优化成每分钟转多大角度。

    java时钟_表盘数字

    采用JAVA编写,该时钟表盘与数字时钟合二为一,可以通过指针时钟与数字时钟来显示系统时间,欢迎大家来分享。

    J2ME中用LWUIT画简单的指针时钟

    J2ME中用LWUIT画简单的指针时钟 by thriller at http://tyche.cn LWUIT(The Lightweight UI Toolkit)是一个轻量级JavaME 用户界面工具包。LWUIT类似Swing 的MVC架构, 支持多种布局(Layouts), 皮肤更换, 字体, ...

    Java课程设计时钟设计

    Java课程设计时钟设计,数字时钟和有指针的时钟。。。。嘿嘿

    基于java.swing时钟.java

    编写一个简单的基于swing的时钟程序,可以在Frame的最上方显示实时时间,显示格式,hh:mm:ss,24小时刻,要求使用SimpleDateFormat来格式化显示样式,并合理安排cpu占用时间

    指针式时钟

    具备钟面和时针、分针、秒针,使用SWING设计界面。

    java 多线程服务器

    java 实现绘制指针时钟 和多线程服务器java 实现绘制指针时钟 和多线程服务器java 实现绘制指针时钟 和多线程服务器java 实现绘制指针时钟 和多线程服务器java 实现绘制指针时钟 和多线程服务器java 实现绘制指针...

    java编写的模拟时钟

    Java语言编写的模拟小时钟,表盘、指针都使用图片显示。。

    java 时钟

    该软件是用java 实现的时钟

    JAVA时钟小应用程序

    JAVA时钟小应用程序 代码片段 { Thread 时针=null, 分针=null,秒针=null; //用来表示时针、分针和秒针的线程。 //表示时针、分针、秒针端点的整型变量: int hour_a,hour_b,munite_a,munite_b,second_a,...

    Java绘制的时钟小程序

    用Java编写的时钟小程序,表盘及指针均是绘制而成

    java时钟界面—代码

    java时钟界面—代码,数字显示和指针显示同时都有,界面设计和电脑相似

    JAVA线程程序设计(小时钟)实验报告(附完整代码).doc

    融筹亭柿藉宫耀舔嘘愿挣实千筑汐肥狭稍绑遵沏磁扔涌丫絮翁其线程程序设计 课题内容和要求 内容:设计和编写一个编写一个指针式时钟程序,应用线程实现时钟的走动。 要求:本实验旨在通过实验,培养学生将JAVA 线程的...

Global site tag (gtag.js) - Google Analytics