<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    zeyuphoenix

    愿我愛的人快樂,愿愛我的人快樂,為了這些,我愿意不快樂.

    Java的指針時鐘

    Java的指針時鐘最基礎的原理和數字時鐘其實差不多,也是利用SwingTimer計時,每隔一定時間重新繪制組件,最后重寫paintComponent方法來更新界面.和之前介紹的時鐘一樣,為了保證時鐘的正確啟動和終止,需要重寫組件的addNotifyremoveNotify方法,在方法內加入Timer的啟動和終止;最后也要重寫組件getPreferredSize方法使組件的大小自動適應.

    首先看最終的效果:

     

    工程的目錄:




    其中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也可以的只是界面比較難看,如下圖:

    所以需要做漂亮點還是要自己去寫一部分代碼的.

    先看繼承關系

    /**

     * 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;

        }

    就可以使用了.

    posted on 2010-04-06 22:03 zeyuphoenix 閱讀(2647) 評論(0)  編輯  收藏 所屬分類: Java的時鐘

    導航

    <2010年4月>
    28293031123
    45678910
    11121314151617
    18192021222324
    2526272829301
    2345678

    統計

    常用鏈接

    留言簿(52)

    隨筆分類

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 久久精品视频免费播放| 中文字幕亚洲一区二区三区| 99久久成人国产精品免费| 亚洲AV无码乱码麻豆精品国产| 久久亚洲高清综合| 青青草国产免费久久久下载| 免费人成在线观看网站品爱网| 一个人看的www在线免费视频| 亚洲人成网站18禁止| 亚洲精品国产专区91在线| 亚洲色婷婷六月亚洲婷婷6月| 免费在线看片网站| 久久精品网站免费观看| 1000部禁片黄的免费看| 暖暖免费日本在线中文| 国产视频精品免费视频| 免费福利资源站在线视频| mm1313亚洲国产精品无码试看| avtt天堂网手机版亚洲| 亚洲手机中文字幕| 亚洲色四在线视频观看| 亚洲爆乳无码一区二区三区| 久久久久亚洲AV无码专区网站 | 免费一级毛片在线播放| 女人被弄到高潮的免费视频| 无码av免费毛片一区二区| 人与禽交免费网站视频| 37pao成人国产永久免费视频| 99热在线免费播放| 久久九九AV免费精品| 久久精品免费观看| 中文字幕无码一区二区免费| 国色精品va在线观看免费视频| 国产成人无码免费网站| 国产精品高清免费网站| 国产精品极品美女自在线观看免费| 成人a毛片视频免费看| 一级A毛片免费观看久久精品 | 2021国内精品久久久久精免费| 久爱免费观看在线网站| 99久久久国产精品免费蜜臀|