WPF利用DrawingContext實(shí)現(xiàn)繪制溫度計(jì)
WPF 使用 DrawingContext 繪制溫度計(jì)
框架使用大于等于.NET40
;
Visual Studio 2022;
項(xiàng)目使用 MIT 開源許可協(xié)議;
定義Interval
步長(zhǎng)、MaxValue
最大溫度值、MinValue
最小溫度值。
CurrentGeometry
重新繪制當(dāng)前刻度的Path
值。
CurrentValue
當(dāng)前值如果發(fā)生變化時(shí)則去重新CurrentGeometry
。
OnRender
繪制如下
RoundedRectangle
溫度計(jì)的外邊框。- 使用方法
DrawText
單字繪制華氏溫度
文本Y
軸變化。 - 使用方法
DrawText
單字繪制攝氏溫度
文本Y
軸變化。 - 使用方法
DrawText
繪制溫度計(jì)兩側(cè)的刻度數(shù)值。 - 使用方法
DrawLine
繪制溫度計(jì)兩側(cè)的刻度線。
實(shí)現(xiàn)代碼
1) 準(zhǔn)備Thermometer.cs如下:
using?System; using?System.Windows; using?System.Windows.Controls; using?System.Windows.Media; namespace?WPFDevelopers.Controls { ????public?class?Thermometer?:?Control ????{ ????????public?static?readonly?DependencyProperty?MaxValueProperty?= ????????????DependencyProperty.Register("MaxValue",?typeof(double),?typeof(Thermometer),?new?UIPropertyMetadata(40.0)); ????????public?static?readonly?DependencyProperty?MinValueProperty?= ????????????DependencyProperty.Register("MinValue",?typeof(double),?typeof(Thermometer),?new?UIPropertyMetadata(-10.0)); ????????///?<summary> ????????///?????當(dāng)前值 ????????///?</summary> ????????public?static?readonly?DependencyProperty?CurrentValueProperty?= ????????????DependencyProperty.Register("CurrentValue",?typeof(double),?typeof(Thermometer), ????????????????new?UIPropertyMetadata(OnCurrentValueChanged)); ????????///?<summary> ????????///?????步長(zhǎng) ????????///?</summary> ????????public?static?readonly?DependencyProperty?IntervalProperty?= ????????????DependencyProperty.Register("Interval",?typeof(double),?typeof(Thermometer),?new?UIPropertyMetadata(10.0)); ????????///?<summary> ????????///?????當(dāng)前值的圖形坐標(biāo)點(diǎn) ????????///?</summary> ????????public?static?readonly?DependencyProperty?CurrentGeometryProperty?= ????????????DependencyProperty.Register("CurrentGeometry",?typeof(Geometry),?typeof(Thermometer),?new?PropertyMetadata( ????????????????Geometry.Parse(@"M?2?132.8 ??????????????????????????????a?4?4?0?0?1?4?-4 ??????????????????????????????h?18 ??????????????????????????????a?4?4?0?0?1?4?4 ??????????????????????????????v?32.2 ??????????????????????????????a?4?4?0?0?1?-4?4 ??????????????????????????????h?-18 ??????????????????????????????a?4?4?0?0?1?-4?-4?z"))); ????????///?<summary> ????????///?????構(gòu)造函數(shù) ????????///?</summary> ????????static?Thermometer() ????????{ ????????????DefaultStyleKeyProperty.OverrideMetadata(typeof(Thermometer), ????????????????new?FrameworkPropertyMetadata(typeof(Thermometer))); ????????} ????????public?double?MaxValue ????????{ ????????????get?=>?(double)GetValue(MaxValueProperty); ????????????set?=>?SetValue(MaxValueProperty,?value); ????????} ????????public?double?MinValue ????????{ ????????????get?=>?(double)GetValue(MinValueProperty); ????????????set?=>?SetValue(MinValueProperty,?value); ????????} ????????public?double?CurrentValue ????????{ ????????????get?=>?(double)GetValue(CurrentValueProperty); ????????????set ????????????{ ????????????????SetValue(CurrentValueProperty,?value); ????????????????PaintPath(); ????????????} ????????} ????????public?double?Interval ????????{ ????????????get?=>?(double)GetValue(IntervalProperty); ????????????set?=>?SetValue(IntervalProperty,?value); ????????} ????????public?Geometry?CurrentGeometry ????????{ ????????????get?=>?(Geometry)GetValue(CurrentGeometryProperty); ????????????set?=>?SetValue(CurrentGeometryProperty,?value); ????????} ????????private?static?void?OnCurrentValueChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e) ????????{ ????????????var?thermometer?=?d?as?Thermometer; ????????????thermometer.CurrentValue?=?Convert.ToDouble(e.NewValue); ????????} ????????public?override?void?OnApplyTemplate() ????????{ ????????????base.OnApplyTemplate(); ????????????PaintPath(); ????????} ????????protected?override?void?OnRender(DrawingContext?drawingContext) ????????{ ????????????var?brush?=?new?SolidColorBrush((Color)ColorConverter.ConvertFromString("#82848A")); ????????????var?rect?=?new?Rect(); ????????????rect.Width?=?30; ????????????rect.Height?=?169; ????????????drawingContext.DrawRoundedRectangle(Brushes.Transparent, ????????????????new?Pen(brush,?2d), ????????????????rect,?8d,?8d); ????????????#region?華氏溫度 ????????????drawingContext.DrawText( ????????????????DrawingContextHelper.GetFormattedText("華", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D), ????????????????new?Point(-49,?115)); ????????????drawingContext.DrawText( ????????????????DrawingContextHelper.GetFormattedText("氏", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D), ????????????????new?Point(-49,?115?+?14)); ????????????drawingContext.DrawText( ????????????????DrawingContextHelper.GetFormattedText("溫", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D), ????????????????new?Point(-49,?115?+?28)); ????????????drawingContext.DrawText( ????????????????DrawingContextHelper.GetFormattedText("度", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D), ????????????????new?Point(-49,?115?+?42)); ????????????#endregion ????????????#region?攝氏溫度 ????????????drawingContext.DrawText( ????????????????DrawingContextHelper.GetFormattedText("攝", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight, ????????????????????14D),?new?Point(75,?115)); ????????????drawingContext.DrawText( ????????????????DrawingContextHelper.GetFormattedText("氏", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight, ????????????????????14D),?new?Point(75,?115?+?14)); ????????????drawingContext.DrawText( ????????????????DrawingContextHelper.GetFormattedText("溫", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight, ????????????????????14D),?new?Point(75,?115?+?28)); ????????????drawingContext.DrawText( ????????????????DrawingContextHelper.GetFormattedText("度", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight, ????????????????????14D),?new?Point(75,?115?+?42)); ????????????#endregion ????????????#region?畫刻度 ????????????var?total_Value?=?MaxValue?-?MinValue; ????????????var?cnt?=?total_Value?/?Interval; ????????????var?one_value?=?161d?/?cnt; ????????????for?(var?i?=?0;?i?<=?cnt;?i++) ????????????{ ????????????????var?formattedText?=?DrawingContextHelper.GetFormattedText($"{MaxValue?-?i?*?Interval}", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight, ????????????????????14D); ????????????????drawingContext.DrawText(formattedText, ????????????????????new?Point(43,?i?*?one_value?-?formattedText.Height?/?2d));?//減去字體高度的一半 ????????????????formattedText?=?DrawingContextHelper.GetFormattedText($"{(MaxValue?-?i?*?Interval)?*?1.8d?+?32d}", ????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D); ????????????????drawingContext.DrawText(formattedText,?new?Point(-13,?i?*?one_value?-?formattedText.Height?/?2d)); ????????????????if?(i?!=?0?&&?i?!=?5) ????????????????{ ????????????????????drawingContext.DrawLine(new?Pen(Brushes.Black,?1d), ????????????????????????new?Point(4,?i?*?one_value),?new?Point(6,?i?*?one_value)); ????????????????????drawingContext.DrawLine(new?Pen(Brushes.Black,?1d), ????????????????????????new?Point(24,?i?*?one_value),?new?Point(26,?i?*?one_value)); ????????????????} ????????????} ????????????#endregion ????????} ????????///?<summary> ????????///?????動(dòng)態(tài)計(jì)算當(dāng)前值圖形坐標(biāo)點(diǎn) ????????///?</summary> ????????private?void?PaintPath() ????????{ ????????????var?one_value?=?161d?/?((MaxValue?-?MinValue)?/?Interval); ????????????var?width?=?26d; ????????????var?height?=?169d?-?(MaxValue?-?CurrentValue)?*?(one_value?/?Interval); ????????????var?x?=?2d; ????????????var?y?=?169d?-?(169d?-?(MaxValue?-?CurrentValue)?*?(one_value?/?Interval)); ????????????CurrentGeometry?=?Geometry.Parse($@"M?2?{y?+?4} ??????????????????????????????a?4?4?0?0?1?4?-4 ??????????????????????????????h?{width?-?8} ??????????????????????????????a?4?4?0?0?1?4?4 ??????????????????????????????v?{height?-?8} ??????????????????????????????a?4?4?0?0?1?-4?4 ??????????????????????????????h?-{width?-?8} ??????????????????????????????a?4?4?0?0?1?-4?-4?z"); ????????} ????} }
2) 使用ThermometerExample.xaml.cs如下:
<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.ThermometerExample" ?????????????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"? ?????????????xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers" ?????????????xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" ?????????????mc:Ignorable="d"? ?????????????d:DesignHeight="450"?d:DesignWidth="800"> ????<Grid> ????????<Border?Background="{DynamicResource?BackgroundSolidColorBrush}"? ????????????????CornerRadius="12" ????????????????Width="400"?Height="400" ????????????????Effect="{StaticResource?NormalShadowDepth}"> ????????????<Grid> ????????????????<Grid.ColumnDefinitions> ????????????????????<ColumnDefinition/> ????????????????????<ColumnDefinition/> ????????????????</Grid.ColumnDefinitions> ????????????????<Slider?x:Name="PART_Slider"?IsSnapToTickEnabled="True" ????????????????Value="10" ????????????????Minimum="-10" ????????????????Maximum="40"? ????????????????Orientation="Vertical" ????????????????Height="300"/> ????????????????<Grid?VerticalAlignment="Center" ??????????????????????Margin="160,0,0,0"> ????????????????????<Path?Fill="{StaticResource?PrimaryMouseOverSolidColorBrush}"? ??????????????????????????Stroke="{StaticResource?PrimaryMouseOverSolidColorBrush}" ??????????????????????????StrokeThickness="1"?Opacity=".6" ??????????????????????????Data="{Binding?ElementName=PART_Thermometer,?Path=CurrentGeometry,Mode=TwoWay}"/> ????????????????????<wpfdev:Thermometer?x:Name="PART_Thermometer" ????????????????????????????????????????CurrentValue="{Binding?ElementName=PART_Slider,Path=Value,Mode=TwoWay}"/> ????????????????</Grid> ????????????????<TextBlock?Text="{Binding?ElementName=PART_Thermometer,Path=CurrentValue,StringFormat={}{0}℃}"? ???????????????????????????FontSize="24"?Grid.Column="1" ???????????????????????????Foreground="{StaticResource?PrimaryPressedSolidColorBrush}"?FontFamily="Bahnschrift" ???????????????????????????HorizontalAlignment="Center"?VerticalAlignment="Center"/> ????????????</Grid> ????????</Border> ????</Grid> </UserControl>
實(shí)現(xiàn)效果
到此這篇關(guān)于WPF利用DrawingContext實(shí)現(xiàn)繪制溫度計(jì)的文章就介紹到這了,更多相關(guān)WPF DrawingContext溫度計(jì)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
通過C#實(shí)現(xiàn)在Word中插入或刪除分節(jié)符
在Word中,分節(jié)符是一種強(qiáng)大的工具,用于將文檔分成不同的部分,每個(gè)部分可以有獨(dú)立的頁(yè)面設(shè)置,如頁(yè)邊距、紙張方向、頁(yè)眉和頁(yè)腳等,本文將介紹如何使用一個(gè)免費(fèi)的.NET庫(kù)通過C#實(shí)現(xiàn)插入或刪除Word分節(jié)符,需要的朋友可以參考下2024-08-08細(xì)說C#中的枚舉:轉(zhuǎn)換、標(biāo)志和屬性
枚舉是 C# 中最有意思的一部分,大部分開發(fā)人員只了解其中的一小部分,甚至網(wǎng)上絕大多數(shù)的教程也只講解了枚舉的一部分。那么,我將通過這篇文章向大家具體講解一下枚舉的知識(shí),需要的朋友可以參考下2020-02-02C#使用whisper.net實(shí)現(xiàn)語(yǔ)音識(shí)別功能
這篇文章主要為大家詳細(xì)介紹了C#如何使用whisper.net實(shí)現(xiàn)語(yǔ)音識(shí)別功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以學(xué)習(xí)一下2023-11-11淺談Visual C#進(jìn)行圖像處理(讀取、保存以及對(duì)像素的訪問)
本文主要介紹利用C#對(duì)圖像進(jìn)行讀取、保存以及對(duì)像素的訪問等操作,介紹的比較簡(jiǎn)單,希望對(duì)初學(xué)者有所幫助。2016-04-04一種c#深拷貝方式完勝java深拷貝(實(shí)現(xiàn)上的對(duì)比分析)
下面小編就為大家?guī)硪黄环Nc#深拷貝方式完勝java深拷貝(實(shí)現(xiàn)上的對(duì)比分析)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07C#中實(shí)現(xiàn)線程同步lock關(guān)鍵字的用法詳解
實(shí)現(xiàn)線程同步的第一種方式是我們經(jīng)常使用的lock關(guān)鍵字,它將包圍的語(yǔ)句塊標(biāo)記為臨界區(qū),這樣一次只有一個(gè)線程進(jìn)入臨界區(qū)并執(zhí)行代碼,接下來通過本文給大家介紹C#中實(shí)現(xiàn)線程同步lock關(guān)鍵字的用法詳解,一起看看吧2016-07-07