Petite pendule en xaml

Description

Je sais que les pendules peuvent être monnaie courante sur un site comme celui-ci, et que les admins doivent certainement en supprimer quelques unes de temps en temps, mais celle-ci à quelque chose de spécial.
"Elle est moche", me direz-vous. He bien oui, mais hormis celà, elle est faite en XAML, et utilise pour le déplacement des aiguilles des animations.
Concrètement, comment ça marche ?
On dessine un cercle (le fond de la pendule), et 3 traits (les aiguilles). On mets toutes les aiguilles à minuit, et on leur affecte une transformation de type rotation, d'angle 0. Ca sert strictement à rien me direz-vous. He bien SI, chers messieurs-dames ! Puisque je nomme cette rotation avec un nom spécial pour chaque aiguilles.
Par exemple, la rotation pour l'aiguille des secondes est appelée AngleSecondes.

C'est dans mon code behind que j'initialise les angles de départ des aiguilles (jai pas réussi à tout faire en XAML). Par exemple, pour l'angle de départ des seconde, cela va être System.DateTime.Now.Second * (360 / 6).
On a donc AngleSecondes.Angle = System.DateTime.Now.Second * (360 / 6) dans le code behind.

J'ai aussi des animations dans mon XAML. une par aiguille, encore une fois. Ces animations vont faire varier l'angle des secondes d'un "From" vers un "To" en un temps déterminé. Pour l'aiguille des secondes, la durée de notre animation est de 60 secondes, 3600 pour l'aiguille des heures, ect...
Le "From" de chaque animation est définit dans le code.
Par exemple, l'animation de notre aiguille des secondes s'appelle AnimSecondes.
AnimSecondes.From est égal à l'angle de départ de l'aiguille des secondes, soit AngleSecondes.
AnimSecondes.To est égal à AnimSecondes.To + 360 (Normal, on veut faire le tour de la pendule).

Il est évident que l'on ne veut pas que l'animation s'arrête à la fin, mais qu'elle reprenne au début à chaque fois... Dans le code XAML, celà se traduit par un RepeatBehavior="Forever".

Source / Exemple :


<Window x:Class="XamlClock.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="XamlClock" Height="300" Width="300" WindowStyle="None"
	x:Name="Fenetre"
    >
	<Canvas>
		<!-- Définition du cadran de l'horloge -->
		<Ellipse x:Name="test" Width="280" Height="280" Canvas.Bottom="10" Canvas.Left="10" Canvas.Right="10" Canvas.Top="10">
			<!-- La couleur du cadran -->
			<Ellipse.Fill>
				<SolidColorBrush Color="Red"></SolidColorBrush>
			</Ellipse.Fill>
			<!-- Un petit effet 3D -->
			<Ellipse.BitmapEffect>
				<BevelBitmapEffect LightAngle="120"></BevelBitmapEffect>
			</Ellipse.BitmapEffect>
		</Ellipse>
		<!-- Définition de l'aiguille des secondes -->
		<Line X1="150" Y1="150" X2="150" Y2="20" StrokeThickness="2" Stroke="Black">
			<!-- On lui applique une transformation de rotation au départ, d'angle 0 (Tranformation nulle).
			Le centre de rotation est le centre de l'horloge (ou le centre de la fenêtre.
			La rotation de départ est donnée dans le code behind.-->
			<Line.RenderTransform>
				<RotateTransform
					Angle="0" CenterX="150"  CenterY="150" x:Name="AngleSecondes" />
			</Line.RenderTransform>
		</Line>
		<!-- Définition de l'aiguille des minutes -->
		<Line X1="150" Y1="150" X2="150" Y2="75" StrokeThickness="2" Stroke="Black">
			<Line.RenderTransform>
				<RotateTransform Angle="0" CenterX="150"  CenterY="150" x:Name="AngleMinutes" />
			</Line.RenderTransform>
		</Line>
		<!-- Définition de l'aiguille des heures -->
		<Line X1="150" Y1="150" X2="150" Y2="100" StrokeThickness="2" Stroke="Black">
			<Line.RenderTransform>
				<RotateTransform Angle="0" CenterX="150"  CenterY="150" x:Name="AngleHeures" />
			</Line.RenderTransform>
		</Line>
	</Canvas>
	<!-- Définition d'un trigger sur la fenêtre. Celui-ci intervient lors du "Loaded" (quand
	la fenêtre est chargée. -->
	<Window.Triggers>
		<EventTrigger RoutedEvent="Window.Loaded">
			<BeginStoryboard>
				<Storyboard>
					<!-- Définition des principales propriétés des animations.
					On a ici 3 animations, une par aiguille. -->
					<DoubleAnimation
					  Duration="0:1:0"
					  Storyboard.TargetName="AngleSecondes"
					Storyboard.TargetProperty="Angle"
					RepeatBehavior="Forever"
					x:Name="AnimSecondes"></DoubleAnimation>
					<DoubleAnimation
					  Duration="1:0:0"
					  Storyboard.TargetName="AngleMinutes"
					Storyboard.TargetProperty="Angle"
					RepeatBehavior="Forever"
					x:Name="AnimMinutes"></DoubleAnimation>
					<DoubleAnimation
					  Duration="43200"
					  Storyboard.TargetName="AngleHeures"
					Storyboard.TargetProperty="Angle"
					RepeatBehavior="Forever"
					x:Name="AnimHeures"></DoubleAnimation>
				</Storyboard>
			</BeginStoryboard>
		</EventTrigger>
	</Window.Triggers>
</Window>

... Et le code behind ...

using System;
using System.Collections.Generic;
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.Shapes;

namespace XamlClock
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>

    public partial class Window1 : System.Windows.Window
    {
        /// <summary>
        /// Constructeur de la classe...
        /// </summary>
        public Window1()
        {
            InitializeComponent();

            // Un peu de maths ?
            // On initialise ici l'angle de départ de chaque aiguille.
            AngleSecondes.Angle = 6 * System.DateTime.Now.Second;
            AngleMinutes.Angle = (360 * ((System.DateTime.Now.Minute * 60) + System.DateTime.Now.Second)) / 3600;
            AngleHeures.Angle = (360 * ((System.DateTime.Now.Hour > 12 ? System.DateTime.Now.Hour - 12 : System.DateTime.Now.Hour) * 3600)) / 43200;
            
            // L'animation va donc partir de l'angle actuel...
            AnimSecondes.From = AngleSecondes.Angle;
            AnimMinutes.From = AngleMinutes.Angle;
            AnimHeures.From = AngleHeures.Angle;

            // ...et l'angle final est l'angle de départ + 360 degrés. Normal, on veut faire le tour de la pendule.
            AnimSecondes.To = AnimSecondes.From + 360;
            AnimMinutes.To = AnimMinutes.From + 360;
            AnimHeures.To = AnimHeures.From + 360;

            // Un petit écouteur pour récupérer la touche escape du clavier et quitter le programme.
            this.KeyUp += new KeyEventHandler(Window1_KeyUp);
        }

        /// <summary>
        /// Permet de récupérer les évènements du clavier survenant sur le formulaire principal.
        /// </summary>
        void Window1_KeyUp(object sender, KeyEventArgs e)
        {
            // Si on appuie sur "Echap", on ferme la fenêtre.
            if(e.Key == Key.Escape)
                this.Close();
        }

    }
}

Conclusion :


Voila, j'espère que cette petite source vous aura donné envie de gratter un peu de XAML et vous aura montré comment utiliser les animations.

Ma question aujourd'hui concerne tout de même la fiabilité de ce code. J'initialise mes angles de départ, et ensuite je laisse l'animation gérer les rotations toutes seules. Que se passe-t-il si le PC rame un coup ? Est-ce que mes aiguilles sont en retard sur l'horaire normale ? Faut-il remettre les pendules à l'heure de temps en temps ?
J'en sais rien, mais je pense que ça doit être quand même pas trop mal géré. Faudra faire des tests, pour voir...

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.