C# WPF로 아래와 같은 아날로그 시계를 만든다.
시계바늘의 움직임은 다음의 식으로 계산된다. 삼각함수가 파라메터로 radian 값을 받기때문에 각도는 radian으로 변형해야 한다.
DateTime currentTime = new DateTime();
currentTime = DateTime.Now;
double radHr = (currentTime.Hour % 12 + currentTime.Minute / 60F) * 30 * Math.PI / 180; // 시침은 1시간에 30도 + 1분에 0.5도
double radMin = (currentTime.Minute) * 6 * Math.PI / 180; // 분침은 1분에 6도씩
double radSec = (currentTime.Second) * 6 * Math.PI / 180; // 초침은 1초에 6도씩
DispatcherTimer 를 불러서 1초에 한번씩 각도를 계산하고 각 바늘의 좌표를 계산한다. DispatcherTimer를 사용하려면 using System.Windows.Threading; 을 써준다.
바늘의 좌표는 다음과 같이 계산한다.
sin(θ) = x / Length à x = sin(θ) * L
cos(θ) = y / Length à y = cos(θ) * L
프로그램의 기본 구조는 다음과 같다. 1초에 한번씩 타이머가 dispatchTimer_Tick 이라는 함수를 불러준다. 이 함수에서 DrawClock()을 호출하여 시계를 그리게 된다.
public MainWindow()
{
InitializeComponent();
dispatchTimer = new DispatcherTimer();
dispatchTimer.Interval = new TimeSpan(0, 0, 1);
dispatchTimer.Tick += dispatchTimer_Tick;
dispatchTimer.Start();
}
void dispatchTimer_Tick(object sender, object e)
{
DrawClock();
}
전체 소스코드는 다음과 같다.
// XAML
<Window x:Class="AnalogClock.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MyClock" Height="400" Width="340">
<Grid >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Canvas Name="Grid1" Margin="10">
<Ellipse Name="Face" Width="300" Height="300" StrokeThickness="3" Stroke="#FFFCC07B"></Ellipse>
<Ellipse Margin="145,145,0,0" Stroke="Chocolate" Fill="Chocolate" Width="10" Height="10" />
</Canvas>
<TextBlock Grid.Row="1" Margin="10" VerticalAlignment="Bottom" HorizontalAlignment="Center" Name="DTimer" FontSize="16" Foreground="#FF084108" FontFamily="Times New Roman" FontStyle="Normal"></TextBlock>
</Grid>
</Window>
// CS 소스
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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; //Dispatcher
namespace AnalogClock
{
public partial class MainWindow : Window
{
private double radius;
private Point Center;
private int hourHand;
private int minHand;
private int secHand;
private DateTime currentTime;
public MainWindow()
{
InitializeComponent();
ClockSettng();
DispatcherTimer Timer = new System.Windows.Threading.DispatcherTimer();
Timer.Tick += new EventHandler(dispatcherTimer_Tick);
Timer.Interval = new TimeSpan(0,0,1); // TimeSpan(0, 0, 1);
Timer.Start();
}
private void ClockSettng()
{
Center = new Point(Face.Width / 2, Face.Height / 2);
radius = Face.Width / 2;
hourHand = (int)(radius * 0.6);
minHand = (int)(radius * 0.8);
secHand = (int)(radius * 0.9);
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
// 화면 지우고...
Grid1.Children.Clear();
currentTime = DateTime.Now;
DTimer.Text = DateTime.Now.ToString();
DrawClockFace();
double radHr = (currentTime.Hour % 12 + currentTime.Minute / 60F) * 30 * Math.PI / 180;
double radMin = (currentTime.Minute) * 6 * Math.PI / 180;
double radSec = (currentTime.Second) * 6 * Math.PI / 180;
DrawHands(radHr, radMin, radSec);
}
private void DrawLine(double x1, double y1, double x2, double y2, SolidColorBrush color, int thickness, Thickness margin)
{
Line line = new Line();
line.X1 = x1; line.Y1 = y1; line.X2 = x2; line.Y2 = y2;
line.Stroke = color;
line.StrokeThickness = thickness;
line.Margin = margin;
Grid1.Children.Add(line);
}
private void DrawHands(double radHr, double radMin, double radSec)
{
// hour
DrawLine(hourHand * Math.Sin(radHr), -hourHand * Math.Cos(radHr), 0, 0,
Brushes.Green, 10, new Thickness(Center.X, Center.Y, 0, 0));
// minute
DrawLine(minHand * Math.Sin(radMin), -minHand * Math.Cos(radMin), 0, 0,
Brushes.Blue, 8, new Thickness(Center.X, Center.Y, 0, 0));
// second
DrawLine(secHand * Math.Sin(radSec), -secHand * Math.Cos(radSec), 0, 0,
Brushes.Red, 3, new Thickness(Center.X, Center.Y, 0, 0));
// center : 중심점
Ellipse center = new Ellipse();
center.Margin = new Thickness(140, 140, 0, 0);
center.Stroke = Brushes.Brown;
center.StrokeThickness = 2;
center.Fill = Brushes.Chocolate;
center.Width = 20;
center.Height = 20;
Grid1.Children.Add(center);
}
private void DrawClockFace()
{
// 시계판 바깥 원
Ellipse outer = new Ellipse();
outer.Stroke = Brushes.Khaki;
outer.StrokeThickness = 3;
outer.Width = 300;
outer.Height = 300;
outer.Fill = Brushes.White;
Grid1.Children.Add(outer);
// 눈금
int L;
int strokeThickness;
SolidColorBrush strokeColor;
for (int deg = 0; deg < 360; deg += 6)
{
double rad = deg * Math.PI / 180;
if (deg % 30 == 0)
{
L = (int)(radius * 0.9);
strokeThickness = 5;
strokeColor = Brushes.Orange;
}
else
{
L = (int)(radius * 0.95);
strokeThickness = 3;
strokeColor = Brushes.YellowGreen;
}
DrawLine(L * Math.Sin(rad), -L * Math.Cos(rad), (radius - 2) * Math.Sin(rad), -(radius - 2) * Math.Cos(rad),
strokeColor, strokeThickness, new Thickness(Center.X, Center.Y, 0, 0));
}
DTimer.Text = DateTime.Now.ToString();
}
}
}
BeeEye 드무
'C# WPF' 카테고리의 다른 글
C# 숫자퍼즐(Jeu De Tacquin) in WPF (0) | 2013.10.19 |
---|---|
Analog Clock in C# WPF(아날로그 시계) - 3 (0) | 2013.10.18 |
Analog Clock in C# WPF using Rotation(아날로그 시계) (0) | 2013.10.18 |
C# WPF 계산기 (0) | 2013.10.02 |
Visual Studio 2012와 2010의 차이점 (0) | 2013.07.10 |