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 ToString()格式设置大全

    针对“asp.net ToString()格式设置大全”的完整攻略,我提供如下讲解。 什么是ToString()方法? 在 ASP.NET 中,ToString() 是 Object 类的一个方法,它可以将对象转换为字符串表示形式。如果你想将一个数值类型转化为字符串来输出到页面或者接口,ToString() 方法是一个非常方便的选择。 如何设置ToStrin…

    C# 2023年6月3日
    00
  • c#爬虫爬取京东的商品信息

    c#爬虫爬取京东的商品信息 爬取京东商品信息需要实现以下步骤: 获取京东的商品列表页面 从列表页面中提取所有商品的链接 访问每个商品链接获取商品详情页面 从商品详情页面中提取商品信息 将商品信息保存到本地或者数据库,可以使用CSV或者Excel格式保存 1. 获取京东的商品列表页面 string url = "https://list.jd.com…

    C# 2023年5月31日
    00
  • C#关键字async/await用法

    下面是”C#关键字async/await用法”的完整攻略。 标题 C#关键字async/await用法 介绍 async/await是C# 5.0版本中新增的关键字,用于简化异步编程的过程。当我们需要在.NET应用程序中执行耗时操作时,通常会遇到线程阻塞、死锁、竞争和上下文问题等问题。使用async/await可以很好地解决这些问题,使得代码更易于编写和理解…

    C# 2023年6月6日
    00
  • C# File.WriteAllText(string path, string contents):将指定文本内容写入文件

    当你需要将一段文本内容写入一个文件中时,可以使用 File.WriteAllText(string path, string contents) 方法。该方法将指定的文件路径和要写入的字符串作为参数,将字符串写入指定的文件中,覆盖原有的文件内容。如果文件不存在,则会被创建。 该方法的语法如下: public static void WriteAllText(…

    C# 2023年4月19日
    00
  • ASP.NET Core中的Razor页面使用视图组件

    在 ASP.NET Core 中,可以使用 Razor 页面和视图组件来构建动态 Web 应用程序。视图组件是一种可重用的 UI 组件,可以在多个 Razor 页面中使用。以下是 ASP.NET Core 中 Razor 页面使用视图组件的完整攻略: 步骤一:创建视图组件 在使用视图组件前,需要创建视图组件。可以在 ASP.NET Core 项目中的 Vie…

    C# 2023年5月17日
    00
  • Entity Framework中执行sql语句

    当使用Entity Framework框架时,可以通过执行SQL语句来访问数据。而执行SQL语句最基本的方式就是通过DbContext.Database属性实现,它提供了ExecuteSqlCommand方法。下面是详细的攻略: 1. 执行SQL查询 1.1 执行SELECT语句并返回结果 可以通过ExecuteSqlCommand方法执行查询语句,如下所示…

    C# 2023年6月3日
    00
  • C#遍历文件夹及其子目录的完整实现方法

    下面是详细讲解“C#遍历文件夹及其子目录的完整实现方法”的攻略: 方案概述 在C#中遍历文件夹及其子目录可以使用递归方式或者非递归方式实现。本文主要介绍递归方式实现的方法,并提供两个示例说明。 递归遍历文件夹 递归遍历文件夹的基本思路是采用递归调用方式,先获取当前目录下的所有文件和子目录,然后对每一个子目录再进行递归操作。具体实现可以使用Directory类…

    C# 2023年6月1日
    00
  • Unity查找游戏物体的六种方式详解

    Unity查找游戏物体的六种方式详解 在Unity中,查找游戏物体是十分常见的操作。本文将介绍Unity中六种查找游戏物体的方式,并且针对每种方式,提供相应的示例进行说明。 1. 通过GameObject.name查找 通过GameObject.name查找游戏物体是最简单、最基本的查找方式。示例代码如下所示: // 通过游戏物体名查找游戏物体 GameOb…

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