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();
        }
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章