Help us understand the problem. What is going on with this article?

WPFのDispatcherTimerクラスを使い簡易アナログ時計を作成する

More than 1 year has passed since last update.

はじめに

WPFのDispatcherTimerクラスを使い、簡単なアナログ時計のサンプルコードです。

概要は以下のとおり。

  • 秒針、分針、時針の3つをLineオブジェクトとして表す。
  • 3つのLineオブジェクトの、RenderTransformプロパティには、RotateTransformを設定する。
  • DispatcherTimerで、1秒おきに、上記RotateTransformの回転角度を変化させる。

実行例

以下に、作成したアプリのスクリーンショットを示します。秒針は1秒おきに動いていきます。

2019-06-01 14_18_29.png

XAMLを定義する

XAMLを示します。
Canvasの中に、3つのLine(時針、分針、秒針)を定義しています。

RotateTransformのAngleプロパティを変化させることで、それぞれの針を動かします。

<Window x:Class="WpfAnalogClock1.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:WpfAnalogClock1"
        mc:Ignorable="d"
        Title="Clock" Height="230" Width="220" Loaded="Window_Loaded" >
    <Canvas Width="200" Height="200">
        <Line x:Name="HourLine"  Stroke="Black" Fill="Black" 
              X1="100" Y1="100" X2="100" Y2="35"              
               StrokeThickness="3" >
            <Line.RenderTransform>
                <RotateTransform  x:Name="AngleHour" Angle="0" 
                                  CenterX="100" CenterY="100"/>
            </Line.RenderTransform>
        </Line>
        <Line x:Name="MinuteLine"  Stroke="Black" Fill="Black" 
              X1="100" Y1="100" X2="100" Y2="15"              
               StrokeThickness="2" >
            <Line.RenderTransform>
                <RotateTransform x:Name="AngleMinute"  Angle="0" 
                                 CenterX="100" CenterY="100"/>
            </Line.RenderTransform>
        </Line>
        <Line x:Name="SecondLine"  Stroke="Black" Fill="LightGray"
              X1="100" Y1="120" X2="100" Y2="10"  >
            <Line.RenderTransform>
                <RotateTransform x:Name="AngleSecond" Angle="0"  
                                 CenterX="100" CenterY="100"/>
            </Line.RenderTransform>
        </Line>
        <Ellipse Fill="Black" Width="6" Height="6" HorizontalAlignment="Center"
            VerticalAlignment="Center" 
            Canvas.Top="97" Canvas.Left="97"/>
    </Canvas>
</Window>

絵心のない僕は、時針、分針、秒針の描画にLineオブジェクトを使いましたが、PolygonやPathを使ってもうすこし時計らしい針にし、背景に文字盤を加えれば、見栄えも良くなると思います。

その際、C#のコードでは、RotateTransform の名前に対して、値を設定していますので、C#側は一切手を入れる必要はないはずです。

C#のコード

C#のコードは、オブジェクトの回転角度を変えるだけですので、とても単純なコードになっています。

WindowのLoadedイベントで、DispatcherTimerオブジェクトを生成し、タイマーをスタートさせます。

Tickイベントが1秒おきに発生しますので、 そのイベントハンドラで、Updateメソッドを呼び出しています。 Updateメソッドでは、現在の時刻を取得し、秒針、分針、時針の針の角度を求め、 それぞれの針に対応するLineオブジェクトの回転角度を更新しています。

このコードは、GitHubで公開しています。

using System;
using System.Windows;
using System.Windows.Threading;

namespace WpfAnalogClock1
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Update();
            DispatcherTimer timer = 
                new DispatcherTimer(DispatcherPriority.Normal, this.Dispatcher);
            timer.Interval = new TimeSpan(0, 0, 1);
            timer.Tick += Timer_Tick;
            timer.Start();
        }

        void Update()
        {
            DateTime dt = DateTime.Now;
            this.AngleSecond.Angle = dt.Second * 360.0 / 60.0;
            this.AngleMinute.Angle = (dt.Minute + dt.Second / 60.0) * 360.0 / 60.0;
            this.AngleHour.Angle = (dt.Hour + dt.Minute / 60.0) * 360.0 / 12;
        }

        void Timer_Tick(object sender, EventArgs e)
        {
            Update();
        }
    }
}
gushwell
株式会社ジード / Microsoft MVP for Developer Technologies 2005-2020 / 著書『実戦で役立つ C#プログラミングのイディオム/定石&パターン』『新・標準プログラマーズライブラリ なるほどなっとく C#入門』『C#プログラミング入門―オブジェクト指向のプログラミング手法を基礎から解説』
https://github.com/gushwell
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away