前言
最近做软件工程课设,因为需要用到可视化界面,经过仔细考察,在小组成员的建议下,最后决定使用XMAL做前台。
题目分析
题目:物理环境包括温度、湿度、大气压力、光照等参量。软件能够以图形化方式,实时显示各参量的状态,比如,显示温度的实时曲线图。具有参量报警功能,能够提供出行意见,具有历史数据查询功能。假设数据以存放在数据库中或文件中。
题目要求用图形化方式实时显示各参量状态,所以前台程序务必足够美观,选用XAML设计窗口界面,C#构建后台。这里主要总结一下XMAL。(我用到的,其实很少很水,主要是对一个构件的总结)。
代码以及注释:
我主要负责生成图表部分,这里主要用了XMAL的一个控件 beto-rodriguez/Live-Charts https://github.com/beto-rodriguez/Live-Charts
<Page x:Class="物理环境感知数据可视化工具.Views.BlankPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:lvc="using:LiveCharts.Uwp" mc:Ignorable="d"> <Grid x:Name="ContentArea" Margin="{StaticResource MediumLeftRightMargin}"> <Grid.RowDefinitions> <RowDefinition x:Name="TitleRow" Height="48"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock x:Name="TitlePage" x:Uid="Blank_Title" Text="Navigation Item 2" Style="{StaticResource PageTitleStyle}" /> <Grid Grid.Row="1" Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}"> <!--The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content. Place your content here.--> <Grid.RowDefinitions> <RowDefinition Height="2*"></RowDefinition> <RowDefinition Height="12*"></RowDefinition> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="8*"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <lvc:CartesianChart Grid.Row="1" Grid.Column="1" Loaded="CartesianChart_Loaded"> <lvc:CartesianChart.Series> <!-- StrokeDashArray="2" 虚线的疏密程度 StrokeThickness="4" 曲线粗细度 Stroke="#1C8FC5" 曲线颜色 Fill="Transparent" 填充为透明 LineSmoothness="2" 曲线平滑度 PointGeometry="{x:Null} 关闭坐标点 PointGeometrySize="10" 坐标点大小 --> <lvc:LineSeries x:Name="myLine" Title="Humidity" Values="{Binding Values1}" StrokeThickness="2.5" Stroke="#1C8FC5" Fill="Transparent" LineSmoothness="2" PointGeometrySize="16" PointForeround="#222E31"/> </lvc:CartesianChart.Series> <!--对X轴进行调整--> <lvc:CartesianChart.AxisX> <lvc:Axis x:Name="myAxis" IsEnabled="False" Labels="{Binding Labels}"> <!--调节单元格框线的宽度,StrokeThickness分隔每行的线(列线)的宽度,StrokeDashArray分割线宽度--> <lvc:Axis.Separator> <lvc:Separator /> </lvc:Axis.Separator> </lvc:Axis> </lvc:CartesianChart.AxisX> <lvc:CartesianChart.AxisY> <!--最外部框线是否合并--> <lvc:Axis IsMerged="False"> <!--调节单元格框线的宽度,StrokeThickness分隔每列的线(行线)的宽度,StrokeDashArray分割线宽度--> <lvc:Axis.Separator> <lvc:Separator StrokeThickness="1" StrokeDashArray="4" Stroke="#404F56" /> </lvc:Axis.Separator> </lvc:Axis> </lvc:CartesianChart.AxisY> </lvc:CartesianChart> <Button Grid.Row="0" Grid.Column="1" Content="T" VerticalAlignment="Bottom" Click="Button_Click_Temperature" FontFamily="SimSun" Background="{x:Null}" FontSize="30" Margin="840,30,0,0"/> <Button Grid.Row="0" Grid.Column="1" Content="H" VerticalAlignment="Bottom" Click="Button_Click_Humidity" FontFamily="SimSun" Background="{x:Null}" FontSize="30" Margin="890,30,0,0"/> <Button Grid.Row="0" Grid.Column="1" Content="L" VerticalAlignment="Bottom" Click="Button_Click_Light" FontFamily="SimSun" Background="{x:Null}" FontSize="30" Margin="940,30,0,0"/> <Button Grid.Row="0" Grid.Column="1" Content="P" VerticalAlignment="Bottom" Click="Button_Click_Pressure" FontFamily="SimSun" Background="{x:Null}" FontSize="30" Margin="990,30,0,0"/> <TextBlock Grid.Row="0" Grid.Column="1" Name="myTitle" HorizontalAlignment="Center" Text="温度" VerticalAlignment="Center" FontSize="35" FontWeight="Normal"/> <TextBlock Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Text="平均高温" FontSize="25" Foreground="#FF706666"/> <TextBlock Grid.Row="2" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Text="历史最高" FontSize="25" Foreground="#FF706666"/> <TextBlock Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Text="平均湿度" FontSize="25" Foreground="#FF706666"/> <TextBlock Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Text="17℃" FontSize="25" FontWeight="Normal" /> <TextBlock Grid.Row="3" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Text="38℃" FontSize="25" Width="95" FontWeight="Normal" /> <TextBlock Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Text="71%" FontSize="25" Width="95" FontWeight="Normal" /> <TextBlock Grid.Row="4" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Text="平均低温" FontSize="25" Foreground="#FF706666"/> <TextBlock Grid.Row="4" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Text="历史最低" FontSize="25" Foreground="#FF706666"/> <TextBlock Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Text="平均光照" FontSize="25" Foreground="#FF706666"/> <TextBlock Grid.Row="5" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Text="13℃" FontSize="25" FontWeight="Normal" /> <TextBlock Grid.Row="5" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Text="-13℃" FontSize="25" Width="95" FontWeight="Normal" /> <TextBlock Grid.Row="5" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Text="16800Lx" FontSize="23" Width="95" FontWeight="Normal" /> </Grid> <!-- Adaptive triggers --> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="WindowStates"> <VisualState x:Name="WideState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="640"/> </VisualState.StateTriggers> </VisualState> <VisualState x:Name="NarrowState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0"/> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="TitlePage.Margin" Value="48,0,12,7"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </Page>
1 using SQLite.Net; 2 using SQLite.Net.Platform.WinRT; 3 using LiveCharts; 4 using Windows.Storage; 5 using Windows.UI.Xaml; 6 using Windows.UI.Xaml.Controls; 7 using System.IO; 8 using System.ComponentModel; 9 using System.Runtime.CompilerServices; 10 11 namespace 物理环境感知数据可视化工具.Views 12 { 13 public sealed partial class BlankPage : Page, INotifyPropertyChanged 14 { 15 ChartValues<double> temperatureValues; 16 17 public BlankPage() 18 { 19 InitializeComponent(); 20 21 //创建数据 22 //CreataData(); 23 temperatureValues = GetTemperatureValues(); 24 } 25 26 public event PropertyChangedEventHandler PropertyChanged; 27 28 private void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null) 29 { 30 if (Equals(storage, value)) 31 { 32 return; 33 } 34 35 storage = value; 36 OnPropertyChanged(propertyName); 37 } 38 39 private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 40 41 42 public void CreataData() 43 { 44 double[] valuesOfTemperature = new double[] { 1, 3, 7, 13, 18, 22, 26, 26, 22, 17, 10, 3 }; 45 double[] valuesOfHumidity = new double[] { 66, 64, 62, 67, 72, 80, 84, 78, 72, 70, 68, 68 }; 46 int[] valuesOfLight = new int[] { 120000, 150000, 180000, 200000, 210000, 230000, 220000, 200000, 170000, 140000, 120000, 110000 }; 47 double[] valuesOfPressure = new double[] { 99.83, 99.79, 99.72, 99.65, 99.63, 99.61, 99.60, 99.62, 99.70, 99.71, 99.76, 99.80 }; 48 using (var conn = AppDatabase.GetDbConnection()) 49 { 50 //需要添加的对象 51 for (int i = 0; i < valuesOfTemperature.Length; ++i) 52 { 53 var addMyData = new HistoricalDataOfTemperature { Id = i + 1, Values = valuesOfTemperature[i] }; 54 conn.Insert(addMyData); 55 } 56 for (int i = 0; i < valuesOfHumidity.Length; ++i) 57 { 58 var addMyData = new HistoricalDataOfHumidity { Id = i + 1, Values = valuesOfHumidity[i] }; 59 conn.Insert(addMyData); 60 } 61 for (int i = 0; i < valuesOfLight.Length; ++i) 62 { 63 var addMyData = new HistoricalDataOfLight { Id = i + 1, Values = valuesOfLight[i] }; 64 conn.Insert(addMyData); 65 } 66 for (int i = 0; i < valuesOfPressure.Length; ++i) 67 { 68 var addMyData = new HistoricalDataOfPressure { Id = i + 1, Values = valuesOfPressure[i] }; 69 conn.Insert(addMyData); 70 } 71 } 72 } 73 74 private void CartesianChart_Loaded(object sender, RoutedEventArgs e) 75 { 76 myLine.Values = temperatureValues; 77 myAxis.Labels = new[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 78 } 79 private void Button_Click_Temperature(object sender, RoutedEventArgs e) 80 { 81 myLine.Values = temperatureValues; 82 myTitle.Text = "温度"; 83 } 84 private void Button_Click_Humidity(object sender, RoutedEventArgs e) 85 { 86 myLine.Values = GetHumidityValues(); 87 myTitle.Text = "湿度"; 88 } 89 private void Button_Click_Light(object sender, RoutedEventArgs e) 90 { 91 myLine.Values = GetLightValues(); 92 myTitle.Text = "光照"; 93 } 94 private void Button_Click_Pressure(object sender, RoutedEventArgs e) 95 { 96 myLine.Values = GetPressureValues(); 97 myTitle.Text = "气压"; 98 } 99 100 //返回从数据库读取的数据 101 private static ChartValues<double> GetTemperatureValues() 102 { 103 104 using (var conn = AppDatabase.GetDbConnection()) 105 { 106 var dbData = conn.Table<HistoricalDataOfTemperature>(); 107 double[] T = new double[12]; 108 foreach (var data in dbData) 109 { 110 T[data.Id - 1] = data.Values; 111 } 112 return new ChartValues<double> { T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10], T[11] }; 113 } 114 } 115 private static ChartValues<double> GetHumidityValues() 116 { 117 118 using (var conn = AppDatabase.GetDbConnection()) 119 { 120 var dbData = conn.Table<HistoricalDataOfHumidity>(); 121 double[] H = new double[12]; 122 foreach (var data in dbData) 123 { 124 H[data.Id - 1] = data.Values; 125 } 126 return new ChartValues<double> { H[0], H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8], H[9], H[10], H[11] }; 127 } 128 } 129 private static ChartValues<double> GetLightValues() 130 { 131 132 using (var conn = AppDatabase.GetDbConnection()) 133 { 134 var dbData = conn.Table<HistoricalDataOfLight>(); 135 double[] L = new double[12]; 136 foreach (var data in dbData) 137 { 138 L[data.Id - 1] = data.Values; 139 } 140 return new ChartValues<double> { L[0], L[1], L[2], L[3], L[4], L[5], L[6], L[7], L[8], L[9], L[10], L[11] }; 141 } 142 } 143 private static ChartValues<double> GetPressureValues() 144 { 145 146 using (var conn = AppDatabase.GetDbConnection()) 147 { 148 var dbData = conn.Table<HistoricalDataOfPressure>(); 149 double[] P = new double[12]; 150 foreach (var data in dbData) 151 { 152 P[data.Id - 1] = data.Values; 153 } 154 return new ChartValues<double> { P[0], P[1], P[2], P[3], P[4], P[5], P[6], P[7], P[8], P[9], P[10], P[11] }; 155 } 156 } 157 } 158 159 public static class AppDatabase 160 { 161 public readonly static string DbPath = Path.Combine(ApplicationData.Current.LocalCacheFolder.Path, "historicalData.db"); 162 163 public static SQLiteConnection GetDbConnection() 164 { 165 // 连接数据库,如果数据库文件不存在则创建一个空数据库。 166 var conn = new SQLiteConnection(new SQLitePlatformWinRT(), DbPath); 167 // 创建 Person 模型对应的表,如果已存在,则忽略该操作。 168 conn.CreateTable<HistoricalDataOfTemperature>(); 169 conn.CreateTable<HistoricalDataOfHumidity>(); 170 conn.CreateTable<HistoricalDataOfLight>(); 171 conn.CreateTable<HistoricalDataOfPressure>(); 172 return conn; 173 } 174 } 175 //温度、湿度、光照、压力数据的定义 176 public class HistoricalDataOfTemperature 177 { 178 public int Id 179 { 180 get; 181 set; 182 } 183 public double Values 184 { 185 get; 186 set; 187 } 188 } 189 public class HistoricalDataOfHumidity 190 { 191 public int Id 192 { 193 get; 194 set; 195 } 196 public double Values 197 { 198 get; 199 set; 200 } 201 } 202 public class HistoricalDataOfLight 203 { 204 public int Id 205 { 206 get; 207 set; 208 } 209 public double Values 210 { 211 get; 212 set; 213 } 214 } 215 public class HistoricalDataOfPressure 216 { 217 public int Id 218 { 219 get; 220 set; 221 } 222 public double Values 223 { 224 get; 225 set; 226 } 227 } 228 }
小结:
感觉自己的这次课设并没有取得理想的成果,尽管付出了很多时间,但是缺乏思考,收获远没有想象的多,希望以后能吸取教训。
时间: 2024-10-13 23:51:46