65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF:皮带时钟

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (43投票s)

2012年5月16日

CPOL

1分钟阅读

viewsIcon

63050

downloadIcon

2791

一款 WPF 皮带时钟

引言

这项工作灵感来源于一款价格昂贵的手表,我在浏览那些充斥着其他令人震惊的高价物品的杂志时看到的。 这款产品价格更实惠,而且没有防弹玻璃。

设计和布局

我在 Expression Blend 中设计了皮带时钟。 皮带由包含TextBlockGrid组成,堆叠在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日:初始发布
© . All rights reserved.