下面我会为你详细讲解“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技术站