仅使用 wpf 中的 xaml 代码创建数字时钟 [英] Create a digital clock using only xaml code in wpf

查看:32
本文介绍了仅使用 wpf 中的 xaml 代码创建数字时钟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以使用动画在xaml中创建数字时钟(没有背景代码标签)

模拟时钟可以通过矩阵转换将当前时间转换为角度来实现,但数字时钟不能这样操作.我尝试了很多方法,但都没有奏效.有谁知道有什么好的实现方法吗?

模拟时钟实现

<窗口.资源><FrameworkElement x:Key="time" Tag={x:Static s:DateTime.Now}/><TransformGroup x:Key="transformHour"><TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Hour}"Y="{Binding Source={StaticResource time},Path=Tag.Minute}"/><MatrixTransform Matrix="30 0 0.5 0 0 0"/></TransformGroup><TransformGroup x:Key="transformMinute"><TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Minute}"Y="{Binding Source={StaticResource time},Path=Tag.Second}"/><MatrixTransform Matrix="6 0 0.1 0 0 0"/></TransformGroup><TransformGroup x:Key="transformSecond"><TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Second}"/><MatrixTransform Matrix="6 0 0 0 0 0"/></TransformGroup><Style TargetType="{x:Type Path}"><Setter 属性="笔画"Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/><Setter Property="StrokeThickness" Value="3"/><Setter Property="StrokeDashCap" Value="Triangle"/></风格></Window.Resources><视图框><画布宽度=200"高度=200"><Canvas.RenderTransform><TranslateTransform X="100" Y="100"/></Canvas.RenderTransform><路径数据="M 0 -90 A 90 90 0 1 1 -0.01 -90"StrokeDashArray="0 3.14157"/><路径数据="M 0 -90 A 90 90 0 1 1 -0.01 -90"StrokeDashArray="0 7.854"StrokeThickness="6"/><Border Background="LightBlue" Width="10" Height="80" RenderTransformOrigin="0.5 0"><Border.RenderTransform><变换组><RotateTransform x:Name="bor_Second" Angle="{Binding Source={StaticResource transformSecond},Path=Value.OffsetX}"/><RotateTransform Angle="180"/></TransformGroup></Border.RenderTransform></边框><Border Background="LightGreen" Width="10" Height="60" RenderTransformOrigin="0.5 0"><Border.RenderTransform><变换组><RotateTransform x:Name="bor_Minute" Angle="{Binding Source={StaticResource transformMinute},Path=Value.OffsetX}"/><RotateTransform Angle="180"/></TransformGroup></Border.RenderTransform></边框><Border Background="LightGray" Width="10" Height="40" RenderTransformOrigin="0.5 0"><Border.RenderTransform><变换组><RotateTransform x:Name="bor_Hour" Angle="{Binding Source={StaticResource transformHour},Path=Value.OffsetX}"/><RotateTransform Angle="180"/></TransformGroup></Border.RenderTransform></边框></画布></视图框><窗口.触发器><EventTrigger RoutedEvent="已加载"><开始故事板><故事板><DoubleAnimation Storyboard.TargetName="bor_Hour"Storyboard.TargetProperty="角度"IsAdditive="真"持续时间="12:0:0"从=0"到=360"RepeatBehavior="永远"/><DoubleAnimation Storyboard.TargetName="bor_Minute"Storyboard.TargetProperty="角度"IsAdditive="真"持续时间="1:0:0"从=0"到=360"RepeatBehavior="永远"/><DoubleAnimation Storyboard.TargetName="bor_Second"Storyboard.TargetProperty="角度"IsAdditive="真"持续时间="0:1:0"从=0"到=360"重复行为=永远"/></故事板></BeginStoryboard></事件触发器></Window.Triggers></窗口>

数字时钟(有错误),感觉用这个思路比较麻烦.有谁知道有什么好的实现方法吗?

<窗口.资源><!--当前时间--><FrameworkElement x:Key="time" Tag="{x:Static s:DateTime.Now}"/><!--当前分钟剩余秒数--><TransformGroup x:Key="transformSecond"><TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Second}" Y="60"/><MatrixTransform Matrix="-1 0 1 0 0 0"/></TransformGroup><!--剩余秒数间隔--><FrameworkElement x:Key="timeSpanSecond"Tag="{Binding Source={StaticResource transformSecond},Path=Value.OffsetX,StringFormat={}{0:F0}}"/><!--当前小时剩余分钟数--><TransformGroup x:Key="transformMinute"><TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Minute}" Y="60"/><MatrixTransform Matrix="-1 1 1 0 0 1"/></TransformGroup><!--剩余分钟间隔--><FrameworkElement x:Key="timeSpanMinute"Tag="{Binding Source={StaticResource transformMinute},Path=Value.OffsetX,StringFormat={}{0:F0}}"/><!--下一分钟--><FrameworkElement x:Key="minuteNext"Tag="{Binding Source={StaticResource transformMinute},Path=Value.OffsetY}"/><!--当天剩余的小时数--><TransformGroup x:Key="transformHour"><TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Hour}" Y="24"/><MatrixTransform Matrix="-1 1 1 0 0 1"/></TransformGroup><!--剩余小时数间隔--><FrameworkElement x:Key="timeSpanHour"Tag="{Binding Source={StaticResource transformHour},Path=Value.OffsetX,StringFormat={}{0:F0}}"/><!--下一小时--><FrameworkElement x:Key="hourNext"Tag="{Binding Source={StaticResource transformHour},Path=Value.OffsetY}"/></Window.Resources><网格><!--宽度:当前秒数--><!--Text:当前剩余秒数(TimeSpan)--><TextBlock x:Name="tbk_Second" Visibility="Hidden"Width="{Binding Source={StaticResource time},Path=Tag.Second}"Text="{Binding Source={StaticResource timeSpanSecond},StringFormat=0:0:{0},Path=Tag}"/><TextBlock x:Name="tbk_Minute" Visibility="Hidden"Width="{Binding Source={StaticResource time},Path=Tag.Minute}"Text="{Binding Source={StaticResource timeSpanMinute},StringFormat=0:{0}:0,Path=Tag}"></TextBlock><TextBlock x:Name="tbk_Hour" Visibility="隐藏"Width="{Binding Source={StaticResource time},Path=Tag.Hour}"Text="{Binding Source={StaticResource timeSpanHour},StringFormat={}{0}:0:0,Path=Tag}"/><TextBlock VerticalAlignment="Center" Horizo​​ntalAlignment="Center"><Run Text="{Binding ElementName=tbk_Hour,Path=Width,StringFormat={}{0:F0}}"/><Run Text=":"/><Run Text="{Binding ElementName=tbk_Minute,Path=Width,StringFormat={}{0:F0}}"/><Run Text=":"/><Run Text="{Binding ElementName=tbk_Second,Path=Width,StringFormat={}{0:F0}}"/></TextBlock></网格><窗口.触发器><EventTrigger RoutedEvent="已加载"><开始故事板><故事板><DoubleAnimation Storyboard.TargetName="tbk_Hour"Storyboard.TargetProperty="宽度"BeginTime="{Binding ElementName=tbk_Minute,Path=Text}"Duration="{Binding ElementName=tbk_Hour,Path=Text}"From="{Binding Source={StaticResource hourNext},Path=Tag}"到="23"/><DoubleAnimation Storyboard.TargetName="tbk_Hour"Storyboard.TargetProperty="宽度"BeginTime="{绑定元素名称=tbk_Hour,Path=Text}"持续时间="24:0:0"从=0"到=23"RepeatBehavior="永远"/><DoubleAnimation Storyboard.TargetName="tbk_Minute"Storyboard.TargetProperty="宽度"BeginTime="{Binding ElementName=tbk_Second,Path=Text}"Duration="{Binding ElementName=tbk_Minute,Path=Text}"From="{Binding Source={StaticResource minuteNext},Path=Tag}"到=59"/><DoubleAnimation Storyboard.TargetName="tbk_Minute"Storyboard.TargetProperty="宽度"BeginTime="{Binding ElementName=tbk_Minute,Path=Text}"持续时间="1:0:0"从=0"到=59"RepeatBehavior="永远"/><双动画Storyboard.TargetName="tbk_Second"Storyboard.TargetProperty="宽度"Duration="{Binding ElementName=tbk_Second,Path=Text}"From="{Binding Source={StaticResource time},Path=Tag.Second}"到=59"/><DoubleAnimation Storyboard.TargetName="tbk_Second"Storyboard.TargetProperty="宽度"BeginTime="{Binding ElementName=tbk_Second,Path=Text}"持续时间="0:1:0"从=0"到=59"RepeatBehavior="永远"/></故事板></BeginStoryboard></事件触发器></Window.Triggers></窗口>

解决方案

我建议你基于文本块和合适的字体来做,就像这样:

只使用一个文本块和字符串格式会更容易,但我已经有了这个例子:)

I wonder if it is possible to create a digital clock in xaml using animation (without background code tags)

The analog clock can be realized by converting the current time to the angle by matrix conversion, but the digital clock can't be operated like this. I tried a lot of methods, but it didn't work. Does anyone know if there is any good way to implement it?

Analog clock implementation

<Window>
    <Window.Resources>
        <FrameworkElement x:Key="time" Tag={x:Static s:DateTime.Now}/>


        <TransformGroup x:Key="transformHour">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Hour}"
                                Y="{Binding Source={StaticResource time},Path=Tag.Minute}"/>
            <MatrixTransform Matrix="30 0 0.5 0 0 0"/>
        </TransformGroup>

        <TransformGroup x:Key="transformMinute">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Minute}"
                                Y="{Binding Source={StaticResource time},Path=Tag.Second}"/>
            <MatrixTransform Matrix="6 0 0.1 0 0 0"/>
        </TransformGroup>

        <TransformGroup x:Key="transformSecond">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Second}"/>
            <MatrixTransform Matrix="6 0 0 0 0 0"/>
        </TransformGroup>

        <Style TargetType="{x:Type Path}">
            <Setter Property="Stroke" 
                    Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
            <Setter Property="StrokeThickness" Value="3"/>
            <Setter Property="StrokeDashCap" Value="Triangle"/>
        </Style>

    </Window.Resources>

    <Viewbox>
        <Canvas Width="200" Height="200">
            <Canvas.RenderTransform>
                <TranslateTransform X="100" Y="100"/>
            </Canvas.RenderTransform>

            <Path Data="M 0 -90 A 90 90 0 1 1 -0.01 -90"
                  StrokeDashArray="0 3.14157" />

            <Path Data="M 0 -90 A 90 90 0 1 1 -0.01 -90"
                  StrokeDashArray="0 7.854"
                  StrokeThickness="6"/>

            <Border Background="LightBlue" Width="10" Height="80" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Second" Angle="{Binding Source={StaticResource transformSecond},Path=Value.OffsetX}"/>
                        <RotateTransform Angle="180"/>
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>

            <Border Background="LightGreen" Width="10" Height="60" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Minute" Angle="{Binding Source={StaticResource transformMinute},Path=Value.OffsetX}"/>
                        <RotateTransform Angle="180"/>
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>

            <Border Background="LightGray" Width="10" Height="40" RenderTransformOrigin="0.5 0">
                <Border.RenderTransform>
                    <TransformGroup>
                        <RotateTransform x:Name="bor_Hour" Angle="{Binding Source={StaticResource transformHour},Path=Value.OffsetX}"/>
                        <RotateTransform Angle="180"/>
                    </TransformGroup>
                </Border.RenderTransform>
            </Border>

        </Canvas>
    </Viewbox>
    <Window.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="bor_Hour"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="12:0:0"
                                    From="0" To="360"
                                    RepeatBehavior="Forever"/>
                    <DoubleAnimation Storyboard.TargetName="bor_Minute"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="1:0:0"
                                    From="0" To="360"
                                    RepeatBehavior="Forever"/>
                    <DoubleAnimation Storyboard.TargetName="bor_Second"
                                    Storyboard.TargetProperty="Angle"
                                    IsAdditive="True"
                                    Duration="0:1:0"
                                    From="0" To="360"
                                    RepeatBehavior="Forever"
                                    />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>
</Window>

Digital clock (there is an error), I feel that it is more troublesome to use this idea. Does anyone know if there is any good way to implement it?

<Window>
    <Window.Resources>

        <!--current time-->
        <FrameworkElement x:Key="time" Tag="{x:Static s:DateTime.Now}"/>


        <!--Current minutes remaining seconds-->
        <TransformGroup x:Key="transformSecond">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Second}" Y="60"/>
            <MatrixTransform Matrix="-1 0 1 0 0 0"/>
        </TransformGroup>

        <!--Remaining seconds interval-->
        <FrameworkElement x:Key="timeSpanSecond" 
                          Tag="{Binding Source={StaticResource transformSecond},Path=Value.OffsetX,StringFormat={}{0:F0}}"/>


        <!--Current hours remaining minutes-->
        <TransformGroup x:Key="transformMinute">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Minute}" Y="60"/>
            <MatrixTransform Matrix="-1 1 1 0 0 1"/>
        </TransformGroup>

        <!--Remaining minute interval-->
        <FrameworkElement x:Key="timeSpanMinute" 
                          Tag="{Binding Source={StaticResource transformMinute},Path=Value.OffsetX,StringFormat={}{0:F0}}"/>

        <!--Next minute-->
        <FrameworkElement x:Key="minuteNext" 
                          Tag="{Binding Source={StaticResource transformMinute},Path=Value.OffsetY}"/>


        <!--Hours remaining on the day-->
        <TransformGroup x:Key="transformHour">
            <TranslateTransform X="{Binding Source={StaticResource time},Path=Tag.Hour}" Y="24"/>
            <MatrixTransform Matrix="-1 1 1 0 0 1"/>
        </TransformGroup>


        <!--Remaining hours interval-->
        <FrameworkElement x:Key="timeSpanHour" 
                          Tag="{Binding Source={StaticResource transformHour},Path=Value.OffsetX,StringFormat={}{0:F0}}"/>

        <!--Next hour-->
        <FrameworkElement x:Key="hourNext" 
                          Tag="{Binding Source={StaticResource transformHour},Path=Value.OffsetY}"/>




    </Window.Resources>

    <Grid>
        <!--Width:Current seconds-->
        <!--Text:Current remaining seconds(TimeSpan)-->
        <TextBlock x:Name="tbk_Second" Visibility="Hidden" 
                   Width="{Binding Source={StaticResource time},Path=Tag.Second}"
                   Text="{Binding Source={StaticResource timeSpanSecond},StringFormat=0:0:{0},Path=Tag}"/>


        <TextBlock x:Name="tbk_Minute" Visibility="Hidden"  
                   Width="{Binding Source={StaticResource time},Path=Tag.Minute}"       
                   Text="{Binding Source={StaticResource timeSpanMinute},StringFormat=0:{0}:0,Path=Tag}">
        </TextBlock>


        <TextBlock x:Name="tbk_Hour" Visibility="Hidden" 
                   Width="{Binding Source={StaticResource time},Path=Tag.Hour}"       
                   Text="{Binding Source={StaticResource timeSpanHour},StringFormat={}{0}:0:0,Path=Tag}"/>

        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">
            <Run Text="{Binding ElementName=tbk_Hour,Path=Width,StringFormat={}{0:F0}}"/>
            <Run Text=":"/>
            <Run Text="{Binding ElementName=tbk_Minute,Path=Width,StringFormat={}{0:F0}}"/>
            <Run Text=":"/>
            <Run Text="{Binding ElementName=tbk_Second,Path=Width,StringFormat={}{0:F0}}"/>
        </TextBlock>


    </Grid>

    <Window.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard >

                    <DoubleAnimation Storyboard.TargetName="tbk_Hour"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Minute,Path=Text}"
                                    Duration="{Binding ElementName=tbk_Hour,Path=Text}"
                                    From="{Binding Source={StaticResource hourNext},Path=Tag}" 
                                    To="23"/>

                    <DoubleAnimation Storyboard.TargetName="tbk_Hour"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Hour,Path=Text}"
                                    Duration="24:0:0"
                                    From="0" 
                                    To="23"        
                                    RepeatBehavior="Forever"/>


                    <DoubleAnimation Storyboard.TargetName="tbk_Minute"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Second,Path=Text}"
                                    Duration="{Binding ElementName=tbk_Minute,Path=Text}"
                                    From="{Binding Source={StaticResource minuteNext},Path=Tag}" 
                                    To="59"/>

                    <DoubleAnimation Storyboard.TargetName="tbk_Minute"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Minute,Path=Text}"
                                    Duration="1:0:0"
                                    From="0" 
                                    To="59"        
                                    RepeatBehavior="Forever"/>


                    <DoubleAnimation 
                                    Storyboard.TargetName="tbk_Second"
                                    Storyboard.TargetProperty="Width"
                                    Duration="{Binding ElementName=tbk_Second,Path=Text}"                                             
                                    From="{Binding Source={StaticResource time},Path=Tag.Second}" 
                                    To="59" 
                                    />
                    <DoubleAnimation Storyboard.TargetName="tbk_Second"
                                    Storyboard.TargetProperty="Width"
                                    BeginTime="{Binding ElementName=tbk_Second,Path=Text}"
                                    Duration="0:1:0"
                                    From="0" 
                                    To="59"        
                                    RepeatBehavior="Forever"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Window.Triggers>

</Window>

解决方案

I recommend you do it based on textblocks and a suitable font like this one:

https://www.keshikan.net/fonts-e.html

Your textblocks are bound to propertys that could be set by an async function calling 'DateTime.Now();' here is a XAML-Example:

            <Border HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,40" Background="DarkGray" BorderThickness="1,1,0,0" BorderBrush="Gray">
                <Grid>  
                    <!-- Displays the actual time in red-->
                    <StackPanel Orientation="Horizontal" Margin="2">
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" Text="{Binding Hour, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" FontFamily="DSEG7 Classic Mini" >:</TextBlock>
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" Text="{Binding Min, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" FontFamily="DSEG7 Classic Mini">:</TextBlock>
                        <TextBlock Opacity="0.6" Foreground="Red" FontSize="20" Text="{Binding Sec, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                    </StackPanel>
                    <!-- Creates a Glow Effect -->
                    <StackPanel Orientation="Horizontal" Margin="2">
                        <StackPanel.Effect>
                            <BlurEffect KernelType="Gaussian" Radius="3"/>
                        </StackPanel.Effect>
                        <TextBlock Foreground="Red" FontSize="20" Text="{Binding Hour, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Foreground="Red" FontSize="20" FontFamily="DSEG7 Classic Mini" >:</TextBlock>
                        <TextBlock Foreground="Red" FontSize="20" Text="{Binding Min, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Foreground="Red" FontSize="20" FontFamily="DSEG7 Classic Mini">:</TextBlock>
                        <TextBlock Foreground="Red" FontSize="20" Text="{Binding Sec, FallbackValue=00, StringFormat=00}" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                    </StackPanel>
                    <!-- Creates the effect of turned of segments -->
                    <StackPanel Orientation="Horizontal" Margin="2">
                        <TextBlock Opacity="0.1" FontSize="20" Text="88" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Opacity="0.1" FontSize="20" FontFamily="DSEG7 Classic Mini" >:</TextBlock>
                        <TextBlock Opacity="0.1" FontSize="20" Text="88" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                        <TextBlock Opacity="0.1" FontSize="20" FontFamily="DSEG7 Classic Mini">:</TextBlock>
                        <TextBlock Opacity="0.1" FontSize="20" Text="88" FontFamily="DSEG7 Classic Mini" ></TextBlock>
                    </StackPanel>
                </Grid>
            </Border>

it would be even easier using only one textblock and a string format but this example I already had lying around :)

这篇关于仅使用 wpf 中的 xaml 代码创建数字时钟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆