C#

WPF 시계만들기 (Rotation 사용)

hyun0229 2022. 6. 16. 01:41

 

디자인

<Window x:Class="_045_RotationClock.MainWindow"
        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:_045_RotationClock"
        mc:Ignorable="d"
        Title="Rotation_Clock" Height="400" Width="400">
    <Grid>
        <Canvas x:Name="aClock" Width="300" Height="300">
            <Rectangle Width="300" Height="300" Stroke="LightSteelBlue"/>
            <Ellipse Width="300" Height="300" Stroke="LightSteelBlue" StrokeThickness="2" RenderTransformOrigin="0.5,0.5"/>
            <Line X1="0" Y1="150" X2="300" Y2="150" Stroke="LightBlue"/>
            <Line X1="150" Y1="0" X2="150" Y2="300" Stroke="LightBlue"/>
            <Line Name="secHand" Stroke="Red" StrokeThickness="2" StrokeEndLineCap="Round"/>
            <Line Name="minHand" Stroke="Green" StrokeThickness="4" StrokeEndLineCap="Round"/>
            <Line Name="hourHand" Stroke="Blue" StrokeThickness="6" StrokeEndLineCap="Round"/>
            <Ellipse Name="center" Width="20" Height="20" Margin="140" Stroke="DarkOliveGreen" StrokeThickness="2" Fill="Chocolate" RenderTransformOrigin="1.17,0.66"/>

        </Canvas>
    </Grid>
</Window>

디자인 Grid를 사용하였고 전과 마찬가지로 시계를 그리기위해 Canvas를 사용하였다.

 

 

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //시계판 그리기
            DrawFace();
            MakeClockHands();

            DispatcherTimer dt=new DispatcherTimer();
            dt.Interval = new TimeSpan(0, 0, 0, 0, 10); //0.01초
            dt.Tick += Dt_Tick;
            dt.Start();
            
        }

전과 마찬가지로 DispatcherTimer를 사용하여 시간을 계산하였다.

 

Dt_Tick()

 private void Dt_Tick(object sender, EventArgs e)
        {
            DateTime c=DateTime.Now;

            double hDeg=c.Hour*30+c.Minute*0.5;
            double mDeg = c.Minute * 6;
            double sDeg = c.Second * 6;

            RotateTransform hRt =new RotateTransform(hDeg);
            hRt.CenterX = hourHand.X1;
            hRt.CenterY = hourHand.Y1;
            hourHand.RenderTransform = hRt;

            RotateTransform mRt = new RotateTransform(mDeg);
            mRt.CenterX = hourHand.X1;
            mRt.CenterY = hourHand.Y1;
            minHand.RenderTransform = mRt;

            RotateTransform sRt = new RotateTransform(sDeg);
            sRt.CenterX = hourHand.X1;
            sRt.CenterY = hourHand.Y1;
            secHand.RenderTransform = sRt;
        }

hDeg, mDeg, sDeg는 각각 시 분 초이며 시는 아날로그 시계의 특성에 맞춰 분을 더해주었다. 

분에도 초에따라 변하게 하고싶다면 초를 더해주면 된다.

 RotateTransform을 각도를 지정하면 회전시켜줍니다.....

 RotateTransform의 자세한 설명은 RotateTransform을 참조

 

 

        private void MakeClockHands()
        {
            int w = 300;
            int h = 300;
            secHand.X1=w/2;
            secHand.Y1 =h/2;
            secHand.X2 =w/2;
            secHand.Y2 = 20;

            minHand.X1 = w / 2;
            minHand.Y1 = h / 2;
            minHand.X2 = w / 2;
            minHand.Y2 = 40;

            hourHand.X1 = w / 2;
            hourHand.Y1 = h / 2;
            hourHand.X2 = w / 2;
            hourHand.Y2 = 60;
        }

sec, min, hourHand는 Xmal에서 생성한 Line의 Name입니다.

 

DrawFace()

 private void DrawFace()
        {
            Line[] marking = new Line[60];
            int w=300;
            for (int i = 0; i < 60; i++)
            {
                marking[i] = new Line();
                marking[i].Stroke = Brushes.LightSteelBlue;
                marking[i].X1 = w / 2;
                marking[i].Y1 = 2;
                marking[i].X2=w/2;
                marking[i].Y2=20;
                if (i%5==0)
                {
                    marking[i].StrokeThickness = 5;
                    marking[i].Y2 = 20;
                }
                else
                {
                    marking[i].StrokeThickness = 2;
                    marking[i].Y2 = 10;
                }
                RotateTransform rt = new RotateTransform(6 * i);
                rt.CenterX = 150;
                rt.CenterY = 150;
                marking[i].RenderTransform = rt;
                aClock.Children.Add(marking[i]);
            }
        }

RotateTransform을 시계의 눈금을 그려줍니다. 5단위로 구분할수 있도록 5로 나누었을때 나머지가 0이 되는 선은 좀더 길고 굵게 그려줍니다. 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace _045_RotationClock
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //시계판 그리기
            DrawFace();
            MakeClockHands();

            DispatcherTimer dt=new DispatcherTimer();
            dt.Interval = new TimeSpan(0, 0, 0, 0, 10); //0.01초
            dt.Tick += Dt_Tick;
            dt.Start();
            
        }

        private void Dt_Tick(object sender, EventArgs e)
        {
            DateTime c=DateTime.Now;

            double hDeg=c.Hour*30+c.Minute*0.5;
            double mDeg = c.Minute * 6;
            double sDeg = c.Second * 6;

            RotateTransform hRt =new RotateTransform(hDeg);
            hRt.CenterX = hourHand.X1;
            hRt.CenterY = hourHand.Y1;
            hourHand.RenderTransform = hRt;

            RotateTransform mRt = new RotateTransform(mDeg);
            mRt.CenterX = hourHand.X1;
            mRt.CenterY = hourHand.Y1;
            minHand.RenderTransform = mRt;

            RotateTransform sRt = new RotateTransform(sDeg);
            sRt.CenterX = hourHand.X1;
            sRt.CenterY = hourHand.Y1;
            secHand.RenderTransform = sRt;
        }

        private void MakeClockHands()
        {
            int w = 300;
            int h = 300;
            secHand.X1=w/2;
            secHand.Y1 =h/2;
            secHand.X2 =w/2;
            secHand.Y2 = 20;

            minHand.X1 = w / 2;
            minHand.Y1 = h / 2;
            minHand.X2 = w / 2;
            minHand.Y2 = 40;

            hourHand.X1 = w / 2;
            hourHand.Y1 = h / 2;
            hourHand.X2 = w / 2;
            hourHand.Y2 = 60;
        }

        private void DrawFace()
        {
            Line[] marking = new Line[60];
            int w=300;
            for (int i = 0; i < 60; i++)
            {
                marking[i] = new Line();
                marking[i].Stroke = Brushes.LightSteelBlue;
                marking[i].X1 = w / 2;
                marking[i].Y1 = 2;
                marking[i].X2=w/2;
                marking[i].Y2=20;
                if (i%5==0)
                {
                    marking[i].StrokeThickness = 5;
                    marking[i].Y2 = 20;
                }
                else
                {
                    marking[i].StrokeThickness = 2;
                    marking[i].Y2 = 10;
                }
                RotateTransform rt = new RotateTransform(6 * i);
                rt.CenterX = 150;
                rt.CenterY = 150;
                marking[i].RenderTransform = rt;
                aClock.Children.Add(marking[i]);
            }
        }
    }
}

전체코드

 

실행결과