WPF实现钟表效果

下面我会为你详细讲解“WPF实现钟表效果”的完整攻略。

一、准备工作

1. 新建WPF应用程序

首先,我们需要新建一个WPF应用程序。

2. 引用PresentationCore、PresentationFramework、WindowsBase三个文件

在新建的WPF应用程序中,我们需要添加 PresentationCore、PresentationFramework、WindowsBase三个引用。

在Visual Studio的“解决方案资源管理器”中,右击“引用”,选择“添加引用”,接着在“程序集”选项卡中勾选 PresentationCore、PresentationFramework、WindowsBase这三个文件,然后点击“确定”按钮,即可完成引用。

3. 编写XAML代码

接下来,我们需要编写XAML代码,创建界面,并声明使用的命名空间。

<Window x:Class="ClockDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF Clock Demo" Height="150" Width="150">
    <Grid>
        <Ellipse Stroke="Gray" StrokeThickness="2" Width="100" Height="100"
                 VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
        <Line X1="50" Y1="50" X2="50" Y2="10" Stroke="Gray" StrokeThickness="2">
            <Line.RenderTransform>
                <RotateTransform x:Name="hourPointerTransform" CenterX="50" CenterY="50"/>
            </Line.RenderTransform>
        </Line>
        <Line X1="50" Y1="50" X2="50" Y2="5" Stroke="Gray" StrokeThickness="2">
            <Line.RenderTransform>
                <RotateTransform x:Name="minutePointerTransform" CenterX="50" CenterY="50"/>
            </Line.RenderTransform>
        </Line>
        <Line X1="50" Y1="50" X2="50" Y2="0" Stroke="Red" StrokeThickness="1">
            <Line.RenderTransform>
                <RotateTransform x:Name="secondPointerTransform" CenterX="50" CenterY="50"/>
            </Line.RenderTransform>
        </Line>
    </Grid>
</Window>

二、实现时钟功能

1. 计时器

我们需要定义一个计时器,并在计时器的Tick事件中更新表针指向。

public partial class MainWindow : Window
{
    private DispatcherTimer _timer;

    public MainWindow()
    {
        InitializeComponent();
        StartTimer();
    }

    public void StartTimer()
    {
        _timer = new DispatcherTimer();
        _timer.Interval = TimeSpan.FromSeconds(1);
        _timer.Tick += _timer_Tick;
        _timer.Start();
    }

    private void _timer_Tick(object sender, EventArgs e)
    {
        var now = DateTime.Now;
        hourPointerTransform.Angle = now.Hour * 30 + now.Minute * 0.5;
        minutePointerTransform.Angle = now.Minute * 6;
        secondPointerTransform.Angle = now.Second * 6;
    }
}

在MainWindow的构造函数中,我们调用了StartTimer方法启动计时器。在计时器的Tick事件中,我们首先获取当前时间,然后将时针、分针、秒针的角度更新为当前时间对应的角度。

2. 模拟渐变色效果

我们为秒针增加一个“闪烁”的效果,模拟出一个渐变色的效果。

private void _timer_Tick(object sender, EventArgs e)
{
    var now = DateTime.Now;
    hourPointerTransform.Angle = now.Hour * 30 + now.Minute * 0.5;
    minutePointerTransform.Angle = now.Minute * 6;

    if (now.Second == 0)
    {
        // 重置秒针的“闪烁”效果,以模拟渐变色的效果
        secondPointerTransform.BeginAnimation(RotateTransform.AngleProperty,
            new DoubleAnimation(now.Second * 6, (now.Second + 1) * 6, TimeSpan.FromSeconds(1)));
    }
    else
    {
        secondPointerTransform.Angle = now.Second * 6;
    }
}

在计时器的Tick事件中,当秒数等于0时,我们重置秒针的“闪烁”效果,以模拟出渐变色的效果。

三、示例说明

示例1

我们定义一个ZodiacClock控件,使用ZodiacClock实现一个12生肖的钟表。

<UserControl x:Class="ClockDemo.ZodiacClock"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Border Background="White" BorderBrush="Gray" BorderThickness="2" CornerRadius="150">
            <Grid>
                <Ellipse HorizontalAlignment="Center" VerticalAlignment="Center" Fill="White" Width="130" Height="130"/>
                <Ellipse HorizontalAlignment="Center" VerticalAlignment="Center" Fill="Gray" Width="120" Height="120"/>
                <Canvas>
                    <Path Data="M0,-130 A130,130 0 0,1 0,130" Stroke="Gray" StrokeThickness="4">
                        <Path.RenderTransform>
                            <RotateTransform Angle="{Binding ZodiacAngle}" CenterX="0" CenterY="0" />
                        </Path.RenderTransform>
                    </Path>
                    <Ellipse Width="20" Height="20" Stroke="Gray" StrokeThickness="2" Fill="White">
                        <Ellipse.RenderTransform>
                            <TranslateTransform X="-10" Y="{Binding YOffset}" />
                        </Ellipse.RenderTransform>
                    </Ellipse>
                </Canvas>
            </Grid>
        </Border>
        <StackPanel Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock Text="生肖" Margin="5,0,5,0"/>
            <ComboBox ItemsSource="{Binding ZodiacList}" DisplayMemberPath="Name" SelectedValuePath="Angle" SelectedValue="{Binding ZodiacAngle}"/>
        </StackPanel>
    </Grid>
</UserControl>
public class Zodiac
{
    public string Name { get; set; }
    public double Angle { get; set; }
}

public partial class ZodiacClock : UserControl
{
    public static readonly DependencyProperty ZodiacAngleProperty =
        DependencyProperty.Register("ZodiacAngle", typeof(double), typeof(ZodiacClock), new FrameworkPropertyMetadata(0d));

    public static readonly DependencyProperty YOffsetProperty =
        DependencyProperty.Register("YOffset", typeof(double), typeof(ZodiacClock), new FrameworkPropertyMetadata(0d));

    public static readonly DependencyProperty ZodiacListProperty =
        DependencyProperty.Register("ZodiacList", typeof(List<Zodiac>), typeof(ZodiacClock), new FrameworkPropertyMetadata(null));

    public double ZodiacAngle
    {
        get { return (double)GetValue(ZodiacAngleProperty); }
        set { SetValue(ZodiacAngleProperty, value); }
    }

    public double YOffset
    {
        get { return (double)GetValue(YOffsetProperty); }
        set { SetValue(YOffsetProperty, value); }
    }

    public List<Zodiac> ZodiacList
    {
        get { return (List<Zodiac>)GetValue(ZodiacListProperty); }
        set { SetValue(ZodiacListProperty, value); }
    }

    public ZodiacClock()
    {
        InitializeComponent();
        DataContext = this;

        ZodiacList = new List<Zodiac>
        {
            new Zodiac{Name="鼠", Angle=30},
            new Zodiac{Name="牛", Angle=60},
            new Zodiac{Name="虎", Angle=90},
            new Zodiac{Name="兔", Angle=120},
            new Zodiac{Name="龙", Angle=150},
            new Zodiac{Name="蛇", Angle=180},
            new Zodiac{Name="马", Angle=210},
            new Zodiac{Name="羊", Angle=240},
            new Zodiac{Name="猴", Angle=270},
            new Zodiac{Name="鸡", Angle=300},
            new Zodiac{Name="狗", Angle=330},
            new Zodiac{Name="猪", Angle=0}
        };

        var timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += timer_Tick;

        Loaded += (s, e) => timer.Start();
    }

    private void timer_Tick(object sender, EventArgs e)
    {
        var now = DateTime.Now;
        var remainder = now.Second % 5;
        YOffset = remainder < 3 ? 10 * remainder : 20 - 10 * remainder;
    }
}

我们新建了一个叫ZodiacClock的UserControl,里面定义了一个“生肖钟表”的控件。在该控件中,我们通过绑定ZodiacAngle和YOffset的值,来定位当时的生肖,并同时通过timer的Tick事件来实现一个微小的晃动效果。

示例2

我们定义一个GreenClock控件,使用GreenClock实现一个环保时钟,并在时钟上显示环保提示语。

<UserControl x:Class="ClockDemo.GreenClock"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <Style x:Key="NumTextStyle" TargetType="{x:Type TextBlock}">
            <Setter Property="FontSize" Value="16"/>
            <Setter Property="Foreground" Value="#FF00703C"/>
            <Setter Property="Margin" Value="5"/>
        </Style>
    </UserControl.Resources>
    <StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
        <Canvas Width="150" Height="150">
            <Ellipse Fill="#FF00703C" Width="150" Height="150"/>
            <Ellipse Fill="White" Width="130" Height="130" Canvas.Left="10" Canvas.Top="10"/>
            <TextBlock Text="环保提醒:"
                       Foreground="#FF00703C" Margin="0,0,0,10"
                       HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
            <TextBlock x:Name="tbReminder" Text="记得关灯、节水哦"
                       Style="{StaticResource NumTextStyle}"
                       Canvas.Left="10" Canvas.Top="10"/>
            <TextBlock x:Name="tbHour" Text="12" Style="{StaticResource NumTextStyle}">
                <TextBlock.RenderTransform>
                    <TranslateTransform X="-10" Y="-60"/>
                </TextBlock.RenderTransform>
            </TextBlock>
            <TextBlock x:Name="tbMinute" Text="00" Style="{StaticResource NumTextStyle}">
                <TextBlock.RenderTransform>
                    <TranslateTransform X="-7" Y="-35"/>
                </TextBlock.RenderTransform>
            </TextBlock>
            <TextBlock x:Name="tbSecond" Text="00" Style="{StaticResource NumTextStyle}">
                <TextBlock.RenderTransform>
                    <TranslateTransform X="-3" Y="-15"/>
                </TextBlock.RenderTransform>
            </TextBlock>
            <Line Stroke="White" StrokeThickness="1" X1="10" Y1="10" X2="10" Y2="35">
                <Line.RenderTransform>
                    <RotateTransform x:Name="hourPointer" CenterX="10" CenterY="75"/>
                </Line.RenderTransform>
            </Line>
            <Line Stroke="White" StrokeThickness="1" X1="10" Y1="10" X2="10" Y2="50">
                <Line.RenderTransform>
                    <RotateTransform x:Name="minutePointer" CenterX="10" CenterY="75"/>
                </Line.RenderTransform>
            </Line>
            <Line Stroke="White" StrokeThickness="1" X1="10" Y1="10" X2="10" Y2="60">
                <Line.RenderTransform>
                    <RotateTransform x:Name="secondPointer" CenterX="10" CenterY="75"/>
                </Line.RenderTransform>
            </Line>
        </Canvas>
    </StackPanel>
</UserControl>
public partial class GreenClock : UserControl
{
    private string[] _reminderList = new string[] 
    {
        "记得关灯、节水哦", "保护环境,从我做起", "为了我们的地球", "要低碳,不要空气污染", "替代传统能源", "再创绿色奇迹"
    };

    public GreenClock()
    {
        InitializeComponent();

        Loaded += (s, e) =>
        {
            var timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(1);
            timer.Tick += timer_Tick;
            timer.Start();

            tbReminder.Text = _reminderList[new Random((int)DateTime.Now.Ticks).Next(0, _reminderList.Length)];
        };
    }

    private void timer_Tick(object sender, EventArgs e)
    {
        var now = DateTime.Now;
        hourPointer.Angle = now.Hour * 30 + now.Minute * 0.5;
        minutePointer.Angle = now.Minute * 6;
        secondPointer.Angle = now.Second * 6;

        if (now.Second == 0)
        {
            tbReminder.Text = _reminderList[new Random((int)DateTime.Now.Ticks).Next(0, _reminderList.Length)];
        }

        tbHour.Text = now.Hour.ToString().PadLeft(2, '0');
        tbMinute.Text = now.Minute.ToString().PadLeft(2, '0');
        tbSecond.Text = now.Second.ToString().PadLeft(2, '0');
    }
}

我们新建了一个叫GreenClock的UserControl,里面定义了一个“环保时钟”的控件。在该控件中,我们通过绑定hourPointer、minutePointer和secondPointer的旋转角度实现指针的动态更新,并通过timer的Tick事件来实现每秒更新时间和随机显示绿色环保提示语。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:WPF实现钟表效果 - Python技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • ASP.NET Core使用HostingStartup增强启动操作方法详解

    在ASP.NET Core中,您可以使用HostingStartup来增强应用程序的启动操作。本攻略将深入探讨如何使用HostingStartup,并提供两个示例说明。 HostingStartup HostingStartup是一个接口,它定义了一个方法Configure方法,该方法在应用程序启动时被调用。您可以使用HostingStartup来执行应用程…

    C# 2023年5月17日
    00
  • c#入门之循环语句使用详解(for循环、do/while)

    C#入门之循环语句使用详解(for循环、do/while) 引言 在编写程序的过程中,经常需要对某些语句进行重复的执行,这时候就需要使用循环语句。本文将详细讲解C#中for循环和do/while循环的使用。 for循环 for循环是最基本的循环语句之一,在C#中也有完整的语法: for (initialization; condition; incremen…

    C# 2023年5月31日
    00
  • C# 实现简单打印的实例代码

    C# 实现简单打印的实例代码 简介 在 C# 中,我们可以通过 System.Drawing.Printing 命名空间提供的 PrintDocument 类来实现简单的文本打印。 步骤 1. 引入命名空间 使用 PrintDocument 类需要引入 System.Drawing.Printing 命名空间。 using System.Drawing.Pr…

    C# 2023年5月31日
    00
  • Unity3D实现人物移动示例

    下面是详细的Unity3D实现人物移动示例攻略。 步骤一:创建场景和人物 首先,打开Unity3D编辑器,创建一个新的场景(File -> New Scene)。然后在场景中创建一个人物模型或导入一个已有的人物模型。 步骤二:添加角色控制器 为了让人物实现移动,我们需要在人物对象上添加一个角色控制器(Character Controller)。在Uni…

    C# 2023年6月3日
    00
  • Parallel.For循环与普通for循环的性能比较

    针对“Parallel.For循环与普通for循环的性能比较”的话题,我将给出一份详细的攻略,包含以下几个部分: 什么是Parallel.For循环? Parallel.For的性能优势是什么? 如何使用Parallel.For循环? Parallel.For循环的示例说明 普通for循环与Parallel.For循环的性能比较 下面就一步一步进行介绍。 1…

    C# 2023年6月7日
    00
  • ASP.NET网站导航及导航控件如何使用

    ASP.NET网站导航及导航控件是用于管理网站导航的重要控件。它可以帮助开发人员快速创建并维护网站导航。此处我将为您提供一份完整攻略,帮助您理解ASP.NET网站导航及导航控件的具体使用方法。 1. 引用导航控件 在ASP.NET网站中,使用导航控件需要在页面中添加导航控件。您可以通过在Web.config文件的配置节点中指定导航控件的信息,或通过标记的方式…

    C# 2023年5月31日
    00
  • C# WinForm创建Excel文件的实例

    以下是C# WinForm创建Excel文件的实例攻略。 第一步:安装Excel应用程序 在使用C# WinForm创建Excel文件之前,我们需要确保已安装Excel应用程序。如果没有安装,可以前往微软官网下载安装。 第二步:添加引用 我们需要通过添加引用来调用Excel的COM组件。在Visual Studio中,右键点击“引用”,选择“添加引用”,在弹…

    C# 2023年6月1日
    00
  • C#获取指定目录最后写入时间的方法

    关于C#获取指定目录最后写入时间的方法,可以使用FileInfo类中的LastWriteTime属性来实现。具体步骤如下: 步骤1. 引入命名空间 首先我们需要在代码文件中引入System.IO命名空间,因为FileInfo类是位于该命名空间下的。代码如下: using System.IO; 步骤2. 定义目录路径 接着,我们需要定义一个目录路径的字符串变量…

    C# 2023年6月2日
    00
合作推广
合作推广
分享本页
返回顶部