zoukankan      html  css  js  c++  java
  • 通过WPF模拟交通红绿灯(图文教程)

    先看一下效果图:

    第一步:新建一个WPF应用程序,这一步的操作就这里省略了。

    第二步:在刚才新建的WPF应用程序中添加一个UserControl命名为:TrafficLightControl,如下图所示

    2011-03-08_145530

    关键代码如下,可以直接拷贝到VS2010即可:

       1:  <UserControl x:Class="WPF绑定转换器.TrafficLightControl"
       2:               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       3:               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       4:               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
       5:               xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       6:               xmlns:myConverter="clr-namespace:WPF绑定转换器"
       7:                Width="120" Height="350">
       8:      <UserControl.Resources>
       9:          <myConverter:ColorConverter x:Key="colorConverter" />
      10:      </UserControl.Resources>
      11:      <Grid>
      12:          <Border Background="Black" CornerRadius="10" BorderBrush="Gray" BorderThickness="2">
      13:              <StackPanel VerticalAlignment="Center">
      14:                  <StackPanel.Resources>
      15:                      <Style TargetType="{x:Type Ellipse}">
      16:                          <Setter Property="Width" Value="100"></Setter>
      17:                          <Setter Property="Height" Value="100"></Setter>
      18:                          <Setter Property="Fill" Value="LightGray"></Setter>
      19:                          <Setter Property="Stroke" Value="Gray"></Setter>
      20:                          <Setter Property="StrokeThickness" Value="2"></Setter>
      21:                          <Setter Property="Margin" Value="4"></Setter>
      22:                      </Style>
      23:                  </StackPanel.Resources>
      24:                  <Ellipse Fill="{Binding State,Converter={StaticResource colorConverter},
                                          ConverterParameter=RED}"/>

    25: <Ellipse Fill="{Binding State,Converter={StaticResource colorConverter},

    ConverterParameter=YELLOW}"/>

      26:                  <Ellipse Fill="{Binding State,Converter={StaticResource colorConverter},
                                          ConverterParameter=GREEN}"/>
      27:              </StackPanel>
      28:          </Border>
      29:      </Grid>
      30:  </UserControl>

    代码解释:为了模拟红绿灯,代码24,25,26行分别创建了3个椭圆,分别设置椭圆的Fill属性,每个椭圆的Fill属性通过绑定的一个状态枚举State{GREEN,YELLOW,RED},Fill属性值实际是一个Brush实例,由于这里用到了枚举值,所以这里同时又创建了一个Converter,在第6行是具体引入这个转换器的方法,下面贴出这个转换器的代码:

       1:      [ValueConversion(typeof(TrafficLight.States), typeof(Brush))]
       2:      public class ColorConverter : IValueConverter
       3:      {
       4:          public enum Lights
       5:          {
       6:              GREEN,
       7:              YELLOW,
       8:              RED
       9:          }
      10:          public object Convert(object value, Type targetType, object parameter, 
                                         System.Globalization.CultureInfo culture)
      11:          {
      12:              TrafficLight.States state = (TrafficLight.States)value;
      13:              Lights light = (Lights)Enum.Parse(typeof(Lights), (string)parameter);
      14:              switch (state)
      15:              {
      16:                  case TrafficLight.States.GREEN:
      17:                      if (light == Lights.GREEN)
      18:                      {
      19:                          return new SolidColorBrush(Colors.Green);
      20:                      }
      21:                      break;
      22:                  case TrafficLight.States.YELLOW:
      23:                      if (light == Lights.YELLOW)
      24:                      {
      25:                          return new SolidColorBrush(Colors.Yellow);
      26:                      }
      27:                      break;
      28:                  case TrafficLight.States.RED:
      29:                      if (light == Lights.RED)
      30:                      {
      31:                          return new SolidColorBrush(Colors.Red);
      32:                      }
      33:                      break;
      34:              }
      35:              return new SolidColorBrush(Colors.LightGray);
      36:          }
      37:   
      38:          public object ConvertBack(object value, Type targetType, object parameter, 
                                             System.Globalization.CultureInfo culture)
      39:          {
      40:              return null;
      41:          }
      42:      }

    代码解释:由于上面创建椭圆的Fill属性值就是一个Color实例,所以这里的转换器实现的基本功能就是,根据传来的枚举状态值(GREEN,RED,YELLOW),返回相应的色彩画刷(new SolidColorBrush(Colors.颜色)),实现了转换器之后,下面继续实现状态枚举State,代码如下:

       1:  public class TrafficLight : INotifyPropertyChanged
       2:      {
       3:          public event PropertyChangedEventHandler PropertyChanged;
       4:   
       5:          private States _state;
       6:   
       7:          public enum States
       8:          {
       9:              GREEN,
      10:              YELLOW,
      11:              RED
      12:          }
      13:   
      14:          public States State
      15:          {
      16:              get
      17:              {
      18:                  return _state;
      19:              }
      20:              set
      21:              {
      22:                  if (value != _state)
      23:                  {
      24:                      _state = value;
      25:                      if (PropertyChanged != null)
      26:                      {
      27:                          PropertyChanged(this,new PropertyChangedEventArgs("State"));
      28:                      }
      29:                  }
      30:              }
      31:          }
      32:      }

    代码解释:状态枚举的定义非常简单,这里不做解释了,拷贝代码只可。

    第三步:实现了第二步操作,第三步主要工作是,在项目里添加一个WPF窗口来容纳第二步创建的用户控件(TrafficLightControl)

    1、页面代码,Xaml代码如下:

       1:  <Window x:Class="WPF绑定转换器.MainWindow"
       2:          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       3:          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       4:          xmlns:my="clr-namespace:WPF绑定转换器"
       5:          Title="MainWindow" Height="512" Width="400" Name="mainWnd" AllowsTransparency="True"
       6:           WindowStyle="None" WindowStartupLocation="CenterScreen" 
                                 MouseLeftButtonDown="mainWnd_MouseLeftButtonDown">
       7:  <Window.Resources>
       8:      <my:TrafficLight State="Red" x:Key="myTrafficLight"/>
       9:      <Style BasedOn="{x:Null}" TargetType="{x:Type Button}">
      10:         <Setter Property="Template">
      11:              <Setter.Value>
      12:                  <ControlTemplate TargetType="{x:Type Button}">
      13: <Grid x:Name="buttonClose">
      14:                         <Ellipse Stroke="{x:Null}" StrokeThickness="1" x:Name="btnEllipse" >
      15:                            <Ellipse.Fill>
      16:                               <RadialGradientBrush>
      17:                                  <GradientStop Color="#BFABA7A4" Offset="0.777"/>
      18:                                  <GradientStop Color="#FF897F77" Offset="1"/>
      19:                               </RadialGradientBrush>
      20:                            </Ellipse.Fill>
      21:                         </Ellipse>
      22:   
      23:
      24:   <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                       HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
      25:</Grid>
      26:                          <ControlTemplate.Triggers>
      27:                              <Trigger Property="IsFocused" Value="True"/>
      28:                              <Trigger Property="IsDefaulted" Value="True"/>
      29:                              <Trigger Property="IsMouseOver" Value="True">
      30:                              <Setter Property="Fill" Value="#FF5D4E3E" TargetName="btnEllipse"/>
      31:                              </Trigger>
      32:                              <Trigger Property="IsPressed" Value="True"/>
      33:                              <Trigger Property="IsEnabled" Value="False"/>
      34:                          </ControlTemplate.Triggers>
      35:                      </ControlTemplate>
      36:                  </Setter.Value>
      37:              </Setter>
      38:          </Style>
      39:      </Window.Resources>
      40:   
      41:      <Border BorderBrush="LightGray" BorderThickness="5">
      42:          <Grid Background="AliceBlue">
      43:              <Grid.RowDefinitions>
      44:                  <RowDefinition Height="30"></RowDefinition>
      45:                  <RowDefinition Height="30"></RowDefinition>
      46:                  <RowDefinition Height="360"></RowDefinition>
      47:                  <RowDefinition Height="*"></RowDefinition>
      48:              </Grid.RowDefinitions>
      49:              <Grid Grid.Row="0">
      50:                  <Grid.ColumnDefinitions>
      51:                      <ColumnDefinition Width="260"></ColumnDefinition>
      52:                      <ColumnDefinition Width="100"></ColumnDefinition>
      53:                      <ColumnDefinition Width="*"></ColumnDefinition>
      54:                  </Grid.ColumnDefinitions>

    55: <TextBlock Grid.Column="0" HorizontalAlignment="Right"

    VerticalAlignment="Center" FontFamily="Arial" FontSize="20" Text="模拟红绿灯实验">

    </TextBlock>

      56:                  <Button Name="btnClose" Grid.Column="1" HorizontalAlignment="Right" 
            VerticalAlignment="Center" Content="X" Width="16" Height="16" Click="btnClose_Click"></Button>
      57:              </Grid>
      58:              <Grid Grid.Row="1">
      59:                  <Grid.ColumnDefinitions>
      60:                      <ColumnDefinition Width="200"></ColumnDefinition>
      61:                      <ColumnDefinition Width="*"></ColumnDefinition>
      62:                  </Grid.ColumnDefinitions>

    63: <Ellipse Name="flagEllipse" HorizontalAlignment="Right"

    VerticalAlignment="Center" Grid.Column="0" Fill="Red" Width="18" Height="18"></Ellipse>

      64:                  <Label Name="lblMessage" HorizontalAlignment="Left" VerticalAlignment="Center" 
                            Grid.Column="1" Height="27"></Label>
      65:              </Grid>
      66:              my:TrafficLightControl Grid.Row="2" DataContext="{StaticResource myTrafficLight}"/>
      67:      <StackPanel Orientation="Horizontal" Grid.Row="3" HorizontalAlignment="Center" Height="30">
      68:      <Button Content="开始模拟" Width="100" Margin="2" Click="ButtonClicked" Name="btnStart"/>
      69:      <Button Content="停止模拟" Width="100" Margin="2" Click="ButtonClicked" Name="btnStop"/>
      70:      </StackPanel>
      71:      </Grid>
      72:      </Border>
      73:  </Window>

    2、后台代码,cs代码:

       1:   /// <summary>
       2:      /// Interaction logic for MainWindow.xaml
       3:      /// </summary>
       4:      public partial class MainWindow : Window
       5:      {
       6:          BackgroundWorker _backgroundWorker = new BackgroundWorker();
       7:          DispatcherTimer dispatcherTimer = new DispatcherTimer();
       8:          public MainWindow()
       9:          {
      10:              InitializeComponent();
      11:              _backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);
      12:              _backgroundWorker.RunWorkerCompleted += 
                       new RunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);
      13:   
      14:              dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
      15:              dispatcherTimer.Interval = TimeSpan.FromMilliseconds(200);
      16:          }
      17:   
      18:          void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      19:          {
      20:              if (e.Cancelled)
      21:              {
      22:                  lblMessage.Content = "终止";
      23:              }
      24:              else if (e.Error != null)
      25:              {
      26:                  lblMessage.Content = "异常";
      27:              }
      28:              else
      29:              {
      30:                  lblMessage.Content = "运行";
      31:              }
      32:          }
      33:   
      34:          void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
      35:          {
      36:              TrafficLight tLight = (TrafficLight)this.FindResource("myTrafficLight");
      37:              if (tLight.State == TrafficLight.States.GREEN)
      38:              {
      39:                  tLight.State = TrafficLight.States.RED;
      40:                  Thread.Sleep(TimeSpan.FromSeconds(5));
      41:              }
      42:              else if (tLight.State == TrafficLight.States.RED)
      43:              {
      44:                  tLight.State = TrafficLight.States.YELLOW;
      45:                  Thread.Sleep(TimeSpan.FromSeconds(2));
      46:              }
      47:              else if (tLight.State == TrafficLight.States.YELLOW)
      48:              {
      49:                  tLight.State = TrafficLight.States.GREEN;
      50:                  Thread.Sleep(TimeSpan.FromSeconds(5));
      51:              }
      52:          }
      53:   
      54:          void dispatcherTimer_Tick(object sender, EventArgs e)
      55:          {
      56:              if (!_backgroundWorker.IsBusy)
      57:              {
      58:                  _backgroundWorker.RunWorkerAsync();
      59:              }
      60:          }
      61:   
      62:          private void ButtonClicked(object sender, RoutedEventArgs e)
      63:          {
      64:              if (sender == btnStart)
      65:              {
      66:                  dispatcherTimer.Start();
      67:                  flagEllipse.Fill = Brushes.Red;
      68:                  DoubleAnimation da = 
                           new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(0.2)));
      69:                  da.AutoReverse = true;
      70:                  da.RepeatBehavior = RepeatBehavior.Forever;
      71:                  flagEllipse.BeginAnimation(Ellipse.OpacityProperty, da);
      72:              }
      73:              else if (sender == btnStop)
      74:              {
      75:                  dispatcherTimer.Stop();
      76:                  lblMessage.Content = "中止";
      77:                  flagEllipse.Fill = Brushes.Black;
      78:              }
      79:          }
      80:   
      81:          private void mainWnd_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
      82:          {
      83:              this.DragMove();
      84:          }
      85:   
      86:          private void btnClose_Click(object sender, RoutedEventArgs e)
      87:          {
      88:              this.Close();
      89:          }
      90:      }

    代码解释:拷贝相应代码即可,为了解决界面更新容易假死的情况,这里利用了异步多线程模型BackgroundWorker,对BackgroundWorker模型用法不清楚的可以BaiDu一下,到处都是。

    总结:事实上为了模拟红绿灯效果,并不是一步到位的,比如我开始是利用三个按钮(红灯、黄灯、绿灯),并添加相应的Click事件在运行时改变State属性值,之后改成通过DispatcherTimer 调度时钟,自动开启BackgroundWorker异步模型,并每隔一段时间查询模型运行状态,也就是模拟红红绿灯的运行状态。

    第四步:一下Demo下载地址

    下载:交通红绿灯

  • 相关阅读:
    CSP 训练赛0925
    赛道修建 NOIP 2018
    C
    B
    游戏得分 建立反图SPFA / bellman
    肥宅快乐树 换根+树形DP/dfs
    组合数例题
    龙珠雷达 双指针+DP
    面试-restful规范
    django-中间件
  • 原文地址:https://www.cnblogs.com/zwq194/p/1975245.html
Copyright © 2011-2022 走看看