WPF:皮带时钟






4.88/5 (43投票s)
一款 WPF 皮带时钟
引言
这项工作灵感来源于一款价格昂贵的手表,我在浏览那些充斥着其他令人震惊的高价物品的杂志时看到的。 这款产品价格更实惠,而且没有防弹玻璃。
设计和布局
我在 Expression Blend 中设计了皮带时钟。 皮带由包含TextBlock
的Grid
组成,堆叠在Canvas
类型的布局容器中。
HourCanvas
以及构成皮带视觉组件的其他元素放置在另一个布局容器中,其ClipToBounds
属性设置为 True。
以下是当所有相关布局容器的ClipToBounds
属性设置为 False 时实际显示的效果。
代码
确保“显示”正确时间的逻辑包含在一个名为TickTock
的类中。 当应用程序加载时,方法SetTimeOnLoad()
调用几个方法以确保突出显示正确的时间。
Public Sub SetTimeOnLoad()
GetTime(currentHour, currentMinute_1, currentMinute_2)
' Highlight hour.
DisplayTimeOnLoad(hourCanvas, currentHour, hourStartGrid, _
hourGridUpperLimit, hourGridLowerLimit)
' Highlight first part of minutes.
DisplayTimeOnLoad(min1Canvas, currentMinute_1, min1StartGrid, _
min1GridUpperLimit, min1GridLowerLimit)
' Highlight second part of minutes.
DisplayTimeOnLoad(min2Canvas, currentMinute_2, min2StartGrid, _
min2GridUpperLimit, min2GridLowerLimit)
End Sub
GetTime()
方法设置几个字段的值为当前时间。
Private Sub GetTime(ByRef hour As Integer, ByRef min1 As Integer, ByRef min2 As Integer)
hour = DateTime.Now.Hour
If (hour > 12) Then
hour -= 12
End If
If (DateTime.Now.Minute.ToString.Length = 1) Then
min1 = 0
min2 = CInt(DateTime.Now.Minute.ToString.Substring(0, 1))
Else
min1 = CInt(DateTime.Now.Minute.ToString.Substring(0, 1))
min2 = CInt(DateTime.Now.Minute.ToString.Substring(1, 1))
End If
End Sub
DisplayTimeOnLoad()
方法确保突出显示正确的时间。
Private Sub DisplayTimeOnLoad(ByRef cnv As Canvas, ByVal currTime As Integer, _
ByVal startGrid As Integer, ByVal upperLimit As Integer, _
ByVal lowerLimit As Integer)
If (currTime < startGrid) Then
' Move grids downwards.
shift = (startGrid - currTime) * gridHeight
While (shift > 0)
For Each grd In cnv.Children
initY = Canvas.GetTop(grd)
newY = initY + 1
Canvas.SetTop(grd, newY)
PlaceGridInLimitPosition(grd, upperLimit, lowerLimit)
Next
shift -= 1
End While
ElseIf (currTime > startGrid) Then
' Move grids upwards.
shift = (currTime - startGrid) * gridHeight
While (shift > 0)
For Each grd In cnv.Children
initY = Canvas.GetTop(grd)
newY = initY - 1
Canvas.SetTop(grd, newY)
PlaceGridInLimitPosition(grd, upperLimit, lowerLimit)
Next
shift -= 1
End While
End If
End Sub
在上面的方法中,感兴趣的Grid
向上或向下移动,以便突出显示正确的时间。 PlaceGridInLimitPosition()
确保超出某个限制的Grid
相应地放置。
Private Sub PlaceGridInLimitPosition(ByRef grd As Grid, ByVal upperLimit As Integer, _
ByVal lowerLimit As Integer)
If (upperLimit = hourGridUpperLimit) AndAlso (lowerLimit = hourGridLowerLimit) Then
If (newY >= 280) Then
Canvas.SetTop(grd, hourGridUpperLimit)
ElseIf (newY <= -240) Then
Canvas.SetTop(grd, hourGridLowerLimit)
End If
ElseIf (upperLimit = min1GridUpperLimit) AndAlso (lowerLimit = min1GridLowerLimit) Then
If (newY >= 120) Then
Canvas.SetTop(grd, min1GridUpperLimit)
ElseIf (newY <= -160) Then
Canvas.SetTop(grd, min1GridLowerLimit)
End If
ElseIf (upperLimit = min2GridUpperLimit) AndAlso (lowerLimit = min2GridLowerLimit) Then
If (newY >= 200) Then
Canvas.SetTop(grd, min2GridUpperLimit)
ElseIf (newY <= -240) Then
Canvas.SetTop(grd, min2GridLowerLimit)
End If
End If
End Sub
方法TimeKeeper_Tick()
处理DispatcherTimer
对象的Tick
事件,其Interval
属性设置为 1 秒,并确保在时间变化时突出显示正确的时间。
Private Sub TimeKeeper_Tick(ByVal sender As Object, ByVal e As EventArgs)
GetTime(currHour, currMin1, currMin2)
' Set new hour.
If (currentHour <> currHour) Then
DisplayNewTime(hourCanvas, hourGridLowerLimit, hourGridUpperLimit)
currentHour = currHour
End If
' Set new first part of minutes.
If (currentMinute_1 <> currMin1) Then
DisplayNewTime(min1Canvas, min1GridLowerLimit, min1GridUpperLimit)
currentMinute_1 = currMin1
End If
' Set new second part of minutes.
If (currentMinute_2 <> currMin2) Then
DisplayNewTime(min2Canvas, min2GridLowerLimit, min2GridUpperLimit)
currentMinute_2 = currMin2
End If
End Sub
DisplayNewTime()
触发执行创建滚动效果的动画。
Private Sub DisplayNewTime(ByRef cnv As Canvas, ByVal lowerLimit As Integer, _
ByVal upperLimit As Integer)
For Each grd As Grid In cnv.Children
initY = Canvas.GetTop(grd)
If (initY <= upperLimit) Then
dblGridAnim.Duration = TimeSpan.FromMilliseconds(1)
dblGridAnim.To = lowerLimit
dblGridAnim.FillBehavior = FillBehavior.HoldEnd
grd.BeginAnimation(Canvas.TopProperty, dblGridAnim)
Else
newY = initY - gridHeight
dblGridAnim.Duration = TimeSpan.FromMilliseconds(800)
dblGridAnim.To = newY
dblGridAnim.FillBehavior = FillBehavior.HoldEnd
grd.BeginAnimation(Canvas.TopProperty, dblGridAnim)
End If
Next
End Sub
结论
就这样了。 希望您从本文中获得了一些有用的知识。 如果有任何错误,请告知我。
历史
- 2012年5月16日:初始发布