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日

相关文章

  • 深入理解C#之接口

    当我们需要定义一个规范或者一个协议,描述某个对象应该具有哪些能力时,可以使用接口。接口可以看做是一种特殊的抽象类,它没有任何实现,只用于描述对象应该有哪些能力。具体来说,一个接口是由一组抽象方法、属性、索引器和事件组成的。可以将接口看做一种契约,实现接口的类型需要履行这个契约,提供指定的能力。 以下是实现接口的基本语法: [public | internal…

    C# 2023年6月7日
    00
  • China.com网站开发规范

    China.com网站开发规范 1. 前言 为了保证China.com网站的稳定性、可维护性和可扩展性,我们需要遵守一套标准的网站开发规范。本文档旨在为China.com网站的开发人员提供一些基本的规范和标准,帮助他们更好地编写规范化的代码并降低维护成本。 2. 代码规范 2.1. HTML规范 使用小写字母标签和属性,避免使用未定义的标签和属性 使用双引号…

    C# 2023年6月7日
    00
  • C# Stream.Flush – 刷新流

    Stream.Flush 方法的作用是将流中的所有缓冲数据都写入其目标(通常是磁盘、网络或其他设备),并清空缓冲区。在调用 Flush 方法后,流可能会保留部分或所有已读取或写入数据的缓存区域,以便再次读取或写入最后部分数据时能够快速访问。 Flush 方法的使用方法如下: // 实例化一个文件流读取器 using (FileStream fileStrea…

    C# 2023年4月19日
    00
  • Javascript的作用域、作用域链以及闭包详解

    Javascript的作用域、作用域链以及闭包详解 什么是作用域? 作用域是指代码中定义变量的区域,也是访问这些变量的规则。在Javascript中常见的作用域有全局作用域和函数作用域。 全局作用域 全局作用域是指定义在最外层的变量,在整个程序执行过程中都可以访问到。例如下面的代码: var name = "Lucy"; function…

    C# 2023年6月7日
    00
  • ASP.NET Core实现自动依赖注入

    在本攻略中,我们将详细讲解如何在ASP.NET Core中实现自动依赖注入,并提供两个示例说明。 步骤一:安装依赖注入包 在ASP.NET Core中实现自动依赖注入之前,您需要安装依赖注入包。以下是一个示例: dotnet add package Microsoft.Extensions.DependencyInjection 在上面的代码中,我们使用do…

    C# 2023年5月17日
    00
  • C#中ArrayList 类的使用详解

    C#中ArrayList 类的使用详解 在C#语言中,ArrayList类是一个非常重要的类,它允许我们在一个集合中存储对象数组。ArrayList类在.NET Framework中作为一个动态数组使用,这就意味着可以在运行时自由地增加或者减少数组的大小,而且类型也是可以变化的。下面我们来详细分析ArrayList类的使用方法。 初始化ArrayList类 …

    C# 2023年6月3日
    00
  • 详解C#获取特定进程CPU和内存使用率

    详解C#获取特定进程CPU和内存使用率 想要获取特定进程的CPU和内存使用率,我们可以使用C#语言结合System.Diagnostics命名空间提供的相关API来实现。 步骤一:获取特定进程 首先我们需要获取我们想要获取的那个进程的实例,可以采用以下方法: Process process = Process.GetProcessesByName(&quot…

    C# 2023年6月7日
    00
  • 用C#生成不重复的随机数的代码

    下面是关于使用C#生成不重复的随机数的完整攻略及示例: 生成不重复的随机数概述 在C#中生成随机数是很常见的需求,但如果要生成不重复的随机数则需要使用一些特殊的技巧。 首先,我们需要生成一个可重复的种子值seed。种子值可以用系统时间、Guid、随机数等值生成。可以使用new Random(seed)初始化Random对象来进行后续的随机数生成操作。 其次,…

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