天天看點

WPF模拟時鐘

一、運作效果圖

WPF模拟時鐘

源代碼連結https://download.csdn.net/download/afu1972715000/11966103

二、xaml

<Window x:Class="WpfClock.WindowClock"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:WpfClock"

        mc:Ignorable="d"

        Title="WindowClock" Height="600" Width="1280" WindowStartupLocation="CenterScreen">

    <Grid>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="*" />

            <ColumnDefinition Width="*" />

        </Grid.ColumnDefinitions>

        <Canvas Grid.Column="0" Name="AnalogCanvs" Width="500" Height="500" >

            <!--<Label Content="08:08:08" FontSize="16" Foreground="Black" Height="Auto" HorizontalAlignment="Center" Name="labTime2" VerticalAlignment="Bottom" Width="Auto" Canvas.Left="201" Canvas.Top="320" />-->

        </Canvas>

        <Canvas Grid.Column="1" Name="digitCanvas" Width="600" Margin="18,35,18,135" >

            <Grid Width="300" Height="300">

                <Image Source="images/clock.png"></Image>

                <!--<Label Name="lab商标" Foreground="White" Margin="0,0,0,211" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="Auto" Width="Auto" FontSize="13" >JackMoon</Label>

                <Label Name="lab建立時間" Foreground="White" Margin="0,91,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" Height="Auto" Width="Auto">1987</Label>-->

                <!-- 秒針定義  -->

                <Rectangle Margin="150,0,149,150" Name="rectangleSecond" Stroke="White" Height="120" VerticalAlignment="Bottom" Width="1">

                    <Rectangle.RenderTransform>

                        <RotateTransform x:Name="secondPointer" CenterX="0" CenterY="120" Angle="0" />

                    </Rectangle.RenderTransform>

                </Rectangle>

                <!-- -->

                <!-- 分鐘定義  -->

                <Rectangle Margin="150,49,149,151" Name="rectangleMinute" Stroke="LightGreen" Width="1">

                    <Rectangle.RenderTransform>

                        <RotateTransform x:Name="minutePointer" CenterX="0" CenterY="100" Angle="45" />

                    </Rectangle.RenderTransform>

                </Rectangle>

                <!-- -->

                <!-- 時針定義  -->

                <Rectangle Margin="150,80,149,150" Name="rectangleHour" Stroke="LightYellow" Width="1">

                    <Rectangle.RenderTransform>

                        <RotateTransform x:Name="hourPointer" CenterX="0" CenterY="70" Angle="90" />

                    </Rectangle.RenderTransform>

                </Rectangle>

                <!---->

              <Label Content="08:08:08" FontSize="16" Foreground="White" Height="Auto" HorizontalAlignment="Center" Margin="114,0,113,86" Name="labTime" VerticalAlignment="Bottom" Width="Auto" />

            </Grid>

        </Canvas>

    </Grid>

</Window>

三、代碼

namespace WpfClock

{

    /// <summary>

    /// WindowClock.xaml 的互動邏輯

    /// </summary>

    public partial class WindowClock : Window

    {

        // 共用字段

        DispatcherTimer timer = new DispatcherTimer();  // 計時器

        DateTime CurrTime = DateTime.Now;                   // 目前時間

        // 模拟時鐘字段定義

        double radius = 250;                              // 圓半徑

        double angle = 360;                               // 角度

        Point Opos = new Point();                       // 原點位置

        Line HourLine, MinuLine, SecdLine;           // 時針、分針、秒針

        Label numberClock = new Label();

        //計時器

        System.Timers.Timer timer2 = new System.Timers.Timer(1000);

        public WindowClock()

        {

            InitializeComponent();

            // 原點位置

            Opos = new Point(250, 250);

            // 初始化計時器

            timer.Interval = TimeSpan.FromMilliseconds(100);

            timer.Tick += Timer_Tick;

            timer.IsEnabled = true;

            timer.Start();

            // 初始化時鐘針

            HourLine = new Line();

            MinuLine = new Line();

            SecdLine = new Line();

            DrawCircle();

            DrawDigit();

            DrawGridLine();

            DrawOCircle();

            DrawNumerClock();

            #region 初始化時間

            secondPointer.Angle = DateTime.Now.Second * 6;

            minutePointer.Angle = DateTime.Now.Minute * 6;

            hourPointer.Angle = (DateTime.Now.Hour * 30) + (DateTime.Now.Minute * 0.5);

            this.labTime.Content = DateTime.Now.ToString("HH:mm:ss");

            #endregion

            timer2.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);

            timer2.Enabled = true;

        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)

        {

            //UI異步更新

            this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>

            {

                //秒針轉動,秒針繞一圈360度,共60秒,是以1秒轉動6度

                secondPointer.Angle = DateTime.Now.Second * 6;

                //分針轉動,分針繞一圈360度,共60分,是以1分轉動6度

                minutePointer.Angle = DateTime.Now.Minute * 6;

                //時針轉動,時針繞一圈360度,共12時,是以1時轉動30度。

                //另外同一個小時内,随着分鐘數的變化(繞一圈60分鐘),時針也在緩慢變化(轉動30度,30/60=0.5)

                hourPointer.Angle = (DateTime.Now.Hour * 30) + (DateTime.Now.Minute * 0.5);

                //更新時間值

                this.labTime.Content = DateTime.Now.ToString("HH:mm:ss");

                //更新時間值

                //this.labTime2.Content = DateTime.Now.ToString("HH:mm:ss");

            }));

        }

        /// <summary>

        /// 畫表盤外圓

        /// </summary>

        private void DrawCircle()

        {

            Ellipse ellipse = new Ellipse();

            ellipse.Stroke = Brushes.DarkGray;

            ellipse.StrokeThickness = 4;

            ellipse.Width = 500;

            ellipse.Height = 500;

            ellipse.Fill = Brushes.Gray;

            Canvas.SetLeft(ellipse, 0);

            Canvas.SetTop(ellipse, 0);

            AnalogCanvs.Children.Add(ellipse);

            Ellipse ellipse1 = new Ellipse();

            ellipse1.Stroke = Brushes.Gray;

            ellipse1.StrokeThickness = 2;

            ellipse1.Width = 510;

            ellipse1.Height = 510;

            Canvas.SetLeft(ellipse1, -5);

            Canvas.SetTop(ellipse1, -5);

            AnalogCanvs.Children.Add(ellipse1);

        }

        ///<summary>

        ///畫數字時鐘

        ///</summary>

        private void DrawNumerClock()

        {

            //< Label Content = "08:08:08" FontSize = "16" Foreground = "Black" Height = "Auto" HorizontalAlignment = "Center" 

            //    Name = "labTime2" VerticalAlignment = "Bottom" Width = "Auto" Canvas.Left = "201" Canvas.Top = "320" />

            //Label numberClock = new Label();

            numberClock.Name = "labTime2";

            numberClock.Content = "08:08:08";

            numberClock.FontSize = 16;

            numberClock.Foreground = new SolidColorBrush(Colors.White); //用固态畫刷填充前景色

            Canvas.SetLeft(numberClock, 220);

            Canvas.SetTop(numberClock, 320);

            AnalogCanvs.Children.Add(numberClock);

        }

        /// <summary>

        /// 圓形表心圓

        /// </summary>

        private void DrawOCircle()

        {

            Ellipse ellipseO = new Ellipse();

            ellipseO.Width = 30;

            ellipseO.Height = 30;

            ellipseO.Fill = Brushes.Blue;

            Canvas.SetLeft(ellipseO, Opos.X - 15);

            Canvas.SetTop(ellipseO, Opos.Y - 15);

            if (AnalogCanvs.Children.Contains(ellipseO))

                AnalogCanvs.Children.Remove(ellipseO);

            AnalogCanvs.Children.Add(ellipseO);

        }

        /// <summary>

        /// 畫圓表盤數字

        /// </summary>

        private void DrawDigit()

        {

            double x, y;

            for (int i = 1; i < 13; i++)

            {

                angle = WrapAngle(i * 360.0 / 12.0) - 90.0;

                angle = ConvertDegreesToRadians(angle);

                x = Opos.X + Math.Cos(angle) * (radius - 36) - 8;

                y = Opos.Y + Math.Sin(angle) * (radius - 36) - 15;

                TextBlock digit = new TextBlock();

                digit.FontSize = 26;

                digit.Text = i.ToString();

                // 數字12位置校正

                if (i == 12)

                {

                    Canvas.SetLeft(digit, x - 8);

                }

                else

                {

                    Canvas.SetLeft(digit, x);

                }

                Canvas.SetTop(digit, y);

                AnalogCanvs.Children.Add(digit);

            }

        }

        /// <summary>

        /// 畫圓表刻度

        /// </summary>

        private void DrawGridLine()

        {

            double x1 = 0, y1 = 0;

            double x2 = 0, y2 = 0;

            for (int i = 0; i < 60; i++)

            {

                double angle1 = WrapAngle(i * 360.0 / 60.0) - 90;

                angle1 = ConvertDegreesToRadians(angle1);

                if (i % 5 == 0)

                {

                    x1 = Math.Cos(angle1) * (radius - 20);

                    y1 = Math.Sin(angle1) * (radius - 20);

                }

                else

                {

                    x1 = Math.Cos(angle1) * (radius - 10);

                    y1 = Math.Sin(angle1) * (radius - 10);

                }

                x2 = Math.Cos(angle1) * (radius - 5);

                y2 = Math.Sin(angle1) * (radius - 5);

                Line line = new Line();

                line.X1 = x1;

                line.Y1 = y1;

                line.X2 = x2;

                line.Y2 = y2;

                line.Stroke = Brushes.Black;

                line.StrokeThickness = 3;

                Canvas.SetLeft(line, Opos.X);

                Canvas.SetTop(line, Opos.Y);

                AnalogCanvs.Children.Add(line);

            }

        }

        /// <summary>

        /// 畫時針

        /// </summary>

        private void DrawHourLine()

        {

            int hour = CurrTime.Hour;

            int minu = CurrTime.Minute;

            double dminu = minu / 60.0;         // 根據分鐘數增加時針偏移

            double dhour = hour + dminu;

            double hour_angle = WrapAngle(dhour * (360.0 / 12.0) - 90.0);

            hour_angle = ConvertDegreesToRadians(hour_angle);

            double x = Math.Cos(hour_angle) * (radius - 100);

            double y = Math.Sin(hour_angle) * (radius - 100);

            HourLine.X1 = 0;

            HourLine.Y1 = 0;

            HourLine.X2 = x;

            HourLine.Y2 = y;

            HourLine.Stroke = Brushes.Black;

            HourLine.StrokeThickness = 4;

            Canvas.SetLeft(HourLine, Opos.X);

            Canvas.SetTop(HourLine, Opos.Y);

            if (AnalogCanvs.Children.Contains(HourLine))

            {

                AnalogCanvs.Children.Remove(HourLine);

            }

            AnalogCanvs.Children.Add(HourLine);

        }

        /// <summary>

        /// 畫分針

        /// </summary>

        private void DrawMinuteLine()

        {

            int minu = CurrTime.Minute;

            int sec = CurrTime.Second;

            double dsec = sec / 60.0;         // 根據秒數增加時針偏移

            double dminu = minu + dsec;

            double minu_angle = WrapAngle(dminu * (360.0 / 60.0) - 90);

            minu_angle = ConvertDegreesToRadians(minu_angle);

            double x = Math.Cos(minu_angle) * (radius - 50);

            double y = Math.Sin(minu_angle) * (radius - 50);

            MinuLine.X1 = 0;

            MinuLine.Y1 = 0;

            MinuLine.X2 = x;

            MinuLine.Y2 = y;

            MinuLine.Stroke = Brushes.Yellow;

            MinuLine.StrokeThickness = 4;

            Canvas.SetLeft(MinuLine, Opos.X);

            Canvas.SetTop(MinuLine, Opos.Y);

            if (AnalogCanvs.Children.Contains(MinuLine))

            {

                AnalogCanvs.Children.Remove(MinuLine);

            }

            AnalogCanvs.Children.Add(MinuLine);

        }

        /// <summary>

        /// 畫秒針

        /// </summary>

        private void DrawSecondLine()

        {

            int second = CurrTime.Second;

            // 秒針正方向點

            double se_angle = WrapAngle(second * (360.0 / 60.0) - 90);

            se_angle = ConvertDegreesToRadians(se_angle);

            double sec_x = Math.Cos(se_angle) * (radius - 40);

            double sec_y = Math.Sin(se_angle) * (radius - 40);

            // 秒針反方向點

            se_angle = WrapAngle(second * (360.0 / 60.0) + 90);

            se_angle = ConvertDegreesToRadians(se_angle);

            double sec_x_ = Math.Cos(se_angle) * (radius - 180);

            double sec_y_ = Math.Sin(se_angle) * (radius - 180);

            SecdLine.X1 = sec_x_;

            SecdLine.Y1 = sec_y_;

            SecdLine.X2 = sec_x;

            SecdLine.Y2 = sec_y;

            SecdLine.Stroke = Brushes.Red;

            SecdLine.StrokeThickness = 3;

            Canvas.SetLeft(SecdLine, Opos.X);

            Canvas.SetTop(SecdLine, Opos.Y);

            if (AnalogCanvs.Children.Contains(SecdLine))

            {

                AnalogCanvs.Children.Remove(SecdLine);

            }

            AnalogCanvs.Children.Add(SecdLine);

        }

        /// <summary>

        /// 角度360度進制

        /// </summary>

        /// <param name="angle"></param>

        /// <returns></returns>

        private double WrapAngle(double angle)

        {

            return angle % 360;

        }

        /// <summary>

        /// 将角度轉為弧度

        /// </summary>

        /// <param name="degrees"></param>

        /// <returns></returns>

        private double ConvertDegreesToRadians(double degrees)

        {

            double radians = (Math.PI / 180) * degrees;

            return radians;

        }

        /// <summary>

        /// 更新小時針、分針、秒針

        /// </summary>

        private void Update()

        {

            DrawHourLine();

            DrawMinuteLine();

            DrawSecondLine();

            //DrawOCircle();

            //DrawNumerClock();

            numberClock.Content = DateTime.Now.ToString("HH:mm:ss");

        }

        /// <summary>

        /// 計時器事件

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void Timer_Tick(object sender, EventArgs e)

        {

            // 更新目前時間

            CurrTime = DateTime.Now;

            // 更新圓盤時針

            Update();

        }

    }

}

繼續閱讀