WPF开发之实现一种三轴机械手控件

作者:一团静火 时间:2021-10-29 19:16:29 

一 引入

WPF开发之实现一种三轴机械手控件

考虑实现一种三轴机器人控件。

三轴机器人用来将某种工件从一个位置运送到另一个位置。

其X轴为手臂轴,可以正向和反向运动,它处于末端,直接接触工件;

其T轴为旋转轴,可以对手臂进行旋转;

其Z轴为升降轴,可以对手臂和旋转部分进行升降。

二 RobotControl

定义出机器人的轴动作枚举,轴的动作分为回原点,正向运动,反向运动。

public enum WaferRobotZAction
{
   Z_Origin,
   Z_CW,
   Z_CCW
}

public enum WaferRobotXAction
{
   X_Origin,
   X_CW,
   X_CCW
}

public enum WaferRobotTAction
{
   T_Origin,
   T_CW,
   T_CCW
}

声明一个WaferRobotControl的自定义控件,它继承自Control类。

定义一个Wafer属性来表示WaferRobot上的工件。

定义表示X轴动作、T轴动作和Z轴动作的依赖属性,它可以被实际的业务数据源绑定。

当实际的业务数据发生改变时,轴动作属性相应改变,并VisualStateManager来转换控件的状态,以触发样式模板中的动画。

public class WaferRobotControl : Control
{
   static WaferRobotControl()
   {
       DefaultStyleKeyProperty.OverrideMetadata(typeof(WaferRobotControl), new FrameworkPropertyMetadata(typeof(WaferRobotControl)));
   }

public static readonly DependencyProperty WaferProperty = DependencyProperty.Register("Wafer", typeof(int), typeof(WaferRobotControl));
   public int Wafer { get => (int)GetValue(WaferProperty); set => SetValue(WaferProperty, value); }

public static readonly DependencyProperty RobotZActionProperty = DependencyProperty.Register(
      "RobotZAction",
      typeof(WaferRobotZAction),
      typeof(WaferRobotControl),
      new PropertyMetadata(WaferRobotZAction.Z_Origin, RobotZActionPropertyChangedCallback));

public WaferRobotZAction RobotZAction
   {
       get => (WaferRobotZAction)GetValue(RobotZActionProperty);
       set => SetValue(RobotZActionProperty, value);
   }

private static void RobotZActionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
       var control = d as WaferRobotControl;
       var oldAct = (WaferRobotZAction)e.OldValue;
       var newAct = (WaferRobotZAction)e.NewValue;
       switch (newAct)
       {
           case WaferRobotZAction.Z_Origin:
               VisualStateManager.GoToState(control, newAct.ToString(), true);
               break;
           case WaferRobotZAction.Z_CW:
               if (newAct != oldAct)
               {
                   VisualStateManager.GoToState(control, newAct.ToString(), true);
               }
               break;
           case WaferRobotZAction.Z_CCW:
               if (newAct != oldAct)
               {
                   VisualStateManager.GoToState(control, newAct.ToString(), true);
               }
               break;
           default:
               break;
       }
   }

public static readonly DependencyProperty RobotXActionProperty = DependencyProperty.Register(
       "RobotXAction",
       typeof(WaferRobotXAction),
       typeof(WaferRobotControl),
       new PropertyMetadata(WaferRobotXAction.X_Origin, RobotXActionPropertyChangedCallback));
   public WaferRobotXAction RobotXAction
   {
       get => (WaferRobotXAction)GetValue(RobotXActionProperty);
       set => SetValue(RobotXActionProperty, value);
   }

private static void RobotXActionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
       var control = d as WaferRobotControl;
       var oldAct = (WaferRobotXAction)e.OldValue;
       var newAct = (WaferRobotXAction)e.NewValue;
       switch (newAct)
       {
           case WaferRobotXAction.X_Origin:
               VisualStateManager.GoToState(control, newAct.ToString(), true);
               break;
           case WaferRobotXAction.X_CW:
               if (newAct != oldAct)
               {
                   VisualStateManager.GoToState(control, newAct.ToString(), true);
               }
               break;
           case WaferRobotXAction.X_CCW:
               if (newAct != oldAct)
               {
                   VisualStateManager.GoToState(control, newAct.ToString(), true);
               }
               break;
           default:
               break;
       }
   }

public static readonly DependencyProperty RobotTActionProperty = DependencyProperty.Register(
       "RobotTAction",
       typeof(WaferRobotTAction),
       typeof(WaferRobotControl),
       new PropertyMetadata(WaferRobotTAction.T_Origin, RobotTActionPropertyChangedCallback));

public WaferRobotTAction RobotTAction
   {
       get => (WaferRobotTAction)GetValue(RobotTActionProperty);
       set => SetValue(RobotTActionProperty, value);
   }

private static void RobotTActionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
       var control = d as WaferRobotControl;
       var oldAct = (WaferRobotTAction)e.OldValue;
       var newAct = (WaferRobotTAction)e.NewValue;
       switch (newAct)
       {
           case WaferRobotTAction.T_Origin:
               VisualStateManager.GoToState(control, newAct.ToString(), true);
               break;
           case WaferRobotTAction.T_CW:
               if (newAct != oldAct)
               {
                   VisualStateManager.GoToState(control, newAct.ToString(), true);
               }
               break;
           case WaferRobotTAction.T_CCW:
               if (newAct != oldAct)
               {
                   VisualStateManager.GoToState(control, newAct.ToString(), true);
               }
               break;
           default:
               break;
       }
   }

public override void OnApplyTemplate()
   {
       base.OnApplyTemplate();
       VisualStateManager.GoToState(this, WaferRobotZAction.Z_Origin.ToString(), true);
       VisualStateManager.GoToState(this, WaferRobotXAction.X_Origin.ToString(), true);
       VisualStateManager.GoToState(this, WaferRobotTAction.T_Origin.ToString(), true);
   }
}

三 Style

控件模板的实现思路。

将机器人的样式分为三部分,不动的底座部分,Z轴部分,包含T轴和X轴的手臂部分。

VisualStateGroup中定义出轴动作的VisualState,编写转换动画。

<SolidColorBrush x:Key="robotBorderBrush" Color="#030303" />
<Style TargetType="{x:Type local:WaferRobotControl}" >
   <Setter Property="Cursor" Value="Hand" />
   <Setter Property="Width" Value="200"/>
   <Setter Property="Height" Value="300"/>
   <Setter Property="Template">
           <Setter.Value>
               <ControlTemplate TargetType="{x:Type local:WaferRobotControl}">
                   <Viewbox x:Name="viewbox" Stretch="Fill">
                       <VisualStateManager.VisualStateGroups>
                           <VisualStateGroup Name="RobotActions">
                               <VisualStateGroup.Transitions>
                                   <VisualTransition To="Z_CW">
                                       <Storyboard FillBehavior="HoldEnd">
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotZAct" Storyboard.TargetProperty="Y">
                                               <LinearDoubleKeyFrame Value="-90" KeyTime="0:0:1"/>
                                           </DoubleAnimationUsingKeyFrames>
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotUpDownAct" Storyboard.TargetProperty="Y">
                                               <LinearDoubleKeyFrame Value="-90" KeyTime="0:0:1"/>
                                           </DoubleAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualTransition>
                                   <VisualTransition To="Z_CCW">
                                       <Storyboard FillBehavior="HoldEnd">
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotZAct" Storyboard.TargetProperty="Y">
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:1"/>
                                           </DoubleAnimationUsingKeyFrames>
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotUpDownAct" Storyboard.TargetProperty="Y">
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:1"/>
                                           </DoubleAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualTransition>
                               </VisualStateGroup.Transitions>
                               <VisualState Name="Z_Origin">
                                   <Storyboard FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotZAct" Storyboard.TargetProperty="Y" >
                                           <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotUpDownAct" Storyboard.TargetProperty="Y" >
                                           <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>
                               <VisualState Name="Z_CW">
                                   <Storyboard  FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotZAct" Storyboard.TargetProperty="Y" Duration="0" >
                                           <LinearDoubleKeyFrame Value="-90" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotUpDownAct" Storyboard.TargetProperty="Y" >
                                           <LinearDoubleKeyFrame Value="-90" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>
                               <VisualState Name="Z_CCW">
                                   <Storyboard FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotZAct" Storyboard.TargetProperty="Y" >
                                           <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotUpDownAct" Storyboard.TargetProperty="Y" >
                                           <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>
                           </VisualStateGroup>

<VisualStateGroup Name="RobotXActions">
                               <VisualStateGroup.Transitions>
                                   <VisualTransition To="X_CW">
                                       <Storyboard FillBehavior="HoldEnd" SpeedRatio="6">
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT1RotateAct" Storyboard.TargetProperty="Angle">
                                               <LinearDoubleKeyFrame Value="90" KeyTime="0:0:0"/>
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:9"/>
                                           </DoubleAnimationUsingKeyFrames>
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2ArmRotateAct" Storyboard.TargetProperty="Angle">
                                               <LinearDoubleKeyFrame Value="-90" KeyTime="0:0:0"/>
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:9"/>
                                           </DoubleAnimationUsingKeyFrames>
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2Act" Storyboard.TargetProperty="X">
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:9"/>
                                               <LinearDoubleKeyFrame Value="2.126" KeyTime="0:0:8"/>
                                               <LinearDoubleKeyFrame Value="8.443" KeyTime="0:0:7"/>
                                               <LinearDoubleKeyFrame Value="18.756" KeyTime="0:0:6"/>
                                               <LinearDoubleKeyFrame Value="32.753" KeyTime="0:0:5"/>
                                               <LinearDoubleKeyFrame Value="50.009" KeyTime="0:0:4"/>
                                               <LinearDoubleKeyFrame Value="70" KeyTime="0:0:3"/>
                                               <LinearDoubleKeyFrame Value="92.117" KeyTime="0:0:2"/>
                                               <LinearDoubleKeyFrame Value="115.689" KeyTime="0:0:1"/>
                                               <LinearDoubleKeyFrame Value="140" KeyTime="0:0:0"/>
                                           </DoubleAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualTransition>
                                   <VisualTransition To="X_CCW">
                                       <Storyboard FillBehavior="HoldEnd" SpeedRatio="6">
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT1RotateAct" Storyboard.TargetProperty="Angle">
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                               <LinearDoubleKeyFrame Value="90" KeyTime="0:0:9"/>
                                           </DoubleAnimationUsingKeyFrames>
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2ArmRotateAct" Storyboard.TargetProperty="Angle">
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                               <LinearDoubleKeyFrame Value="-90" KeyTime="0:0:9"/>
                                           </DoubleAnimationUsingKeyFrames>
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2Act" Storyboard.TargetProperty="X">
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                               <LinearDoubleKeyFrame Value="2.126" KeyTime="0:0:1"/>
                                               <LinearDoubleKeyFrame Value="8.443" KeyTime="0:0:2"/>
                                               <LinearDoubleKeyFrame Value="18.756" KeyTime="0:0:3"/>
                                               <LinearDoubleKeyFrame Value="32.753" KeyTime="0:0:4"/>
                                               <LinearDoubleKeyFrame Value="50.009" KeyTime="0:0:5"/>
                                               <LinearDoubleKeyFrame Value="70" KeyTime="0:0:6"/>
                                               <LinearDoubleKeyFrame Value="92.117" KeyTime="0:0:7"/>
                                               <LinearDoubleKeyFrame Value="115.689" KeyTime="0:0:8"/>
                                               <LinearDoubleKeyFrame Value="140" KeyTime="0:0:9"/>
                                           </DoubleAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualTransition>
                               </VisualStateGroup.Transitions>

<VisualState Name="X_Origin">
                                   <Storyboard FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT1RotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="90" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2ArmRotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="-90" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2Act" Storyboard.TargetProperty="X">
                                           <LinearDoubleKeyFrame Value="140" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>

<VisualState Name="X_CW">
                                   <Storyboard FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT1RotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2ArmRotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2Act" Storyboard.TargetProperty="X">
                                           <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>
                               <VisualState Name="X_CCW">
                                   <Storyboard FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT1RotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="90" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2ArmRotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="-90" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="armXT2Act" Storyboard.TargetProperty="X">
                                           <LinearDoubleKeyFrame Value="140" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>
                           </VisualStateGroup>

<VisualStateGroup Name="RobotTActions">
                               <VisualStateGroup.Transitions>
                                   <VisualTransition To="T_Origin">
                                       <Storyboard FillBehavior="HoldEnd">
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotRotateAct" Storyboard.TargetProperty="Angle">
                                               <LinearDoubleKeyFrame Value="90" KeyTime="0:0:1"/>
                                           </DoubleAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualTransition>
                                   <VisualTransition To="T_CW">
                                       <Storyboard FillBehavior="HoldEnd">
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotRotateAct" Storyboard.TargetProperty="Angle">
                                               <LinearDoubleKeyFrame Value="180" KeyTime="0:0:1"/>
                                           </DoubleAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualTransition>
                                   <VisualTransition To="T_CCW">
                                       <Storyboard FillBehavior="HoldEnd">
                                           <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotRotateAct" Storyboard.TargetProperty="Angle">
                                               <LinearDoubleKeyFrame Value="0" KeyTime="0:0:1"/>
                                           </DoubleAnimationUsingKeyFrames>
                                       </Storyboard>
                                   </VisualTransition>
                               </VisualStateGroup.Transitions>

<VisualState Name="T_Origin">
                                   <Storyboard FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotRotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="90" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>
                               <VisualState Name="T_CCW">
                                   <Storyboard FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotRotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>
                               <VisualState Name="T_CW">
                                   <Storyboard FillBehavior="HoldEnd">
                                       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="robotRotateAct" Storyboard.TargetProperty="Angle">
                                           <LinearDoubleKeyFrame Value="180" KeyTime="0:0:0"/>
                                       </DoubleAnimationUsingKeyFrames>
                                   </Storyboard>
                               </VisualState>
                           </VisualStateGroup>
                       </VisualStateManager.VisualStateGroups>
                       <Canvas Width="200" Height="300" >
                           <Canvas x:Name="robotZ" Width="40" Height="120" Canvas.Top="170" Canvas.Left="80" >
                               <Canvas.RenderTransform>
                                   <TransformGroup>
                                       <TranslateTransform x:Name="robotZAct"></TranslateTransform>
                                   </TransformGroup>
                               </Canvas.RenderTransform>
                               <Path Stroke="#030303" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
                                   <Path.Fill>
                                       <LinearGradientBrush  EndPoint="1,0.5" StartPoint="0,0.5">
                                           <GradientStop Color="#6B696A" Offset="0" />
                                           <GradientStop Color="#6B696A" Offset="1" />
                                           <GradientStop Color="#A1A7BE" Offset="0.5" />
                                       </LinearGradientBrush>
                                   </Path.Fill>
                                   <Path.Data>
                                       <PathGeometry>
                                           <PathFigure StartPoint="0 20" IsClosed="True">
                                               <LineSegment Point="0 2"/>
                                               <LineSegment Point="2 2"/>
                                               <LineSegment Point="5 5"/>
                                               <LineSegment Point="35 5" />
                                               <LineSegment Point="38 2"/>
                                               <LineSegment Point="40 2"/>
                                               <LineSegment Point="40 20" />
                                               <LineSegment Point="0 20" />
                                           </PathFigure>

<PathFigure StartPoint="4 20" >
                                               <LineSegment Point="4 24"/>
                                               <LineSegment Point="36 24" />
                                               <LineSegment Point="36 20"/>
                                           </PathFigure>

<PathFigure StartPoint="4 24" >
                                               <LineSegment Point="2 24"/>
                                               <LineSegment Point="2 28"/>
                                               <LineSegment Point="4 28"/>
                                               <LineSegment Point="36 28" />
                                               <LineSegment Point="38 28" />
                                               <LineSegment Point="38 24"/>
                                               <LineSegment Point="36 24"/>
                                           </PathFigure>
                                       </PathGeometry>
                                   </Path.Data>
                               </Path>
                               <Path Stroke="#030303"  StrokeStartLineCap="Round" StrokeEndLineCap="Round">
                                   <Path.Fill>
                                       <LinearGradientBrush  EndPoint="1,0.5" StartPoint="0,0.5">
                                           <GradientStop Color="#6B696A" Offset="0" />
                                           <GradientStop Color="#6B696A" Offset="1" />
                                           <GradientStop Color="#A1A7BE" Offset="0.5" />
                                       </LinearGradientBrush>
                                   </Path.Fill>
                                   <Path.Data>
                                       <PathGeometry>
                                           <PathFigure StartPoint="2 28.5" >
                                               <LineSegment Point="2 120"/>
                                               <LineSegment Point="38 120"/>
                                               <LineSegment Point="38 28.5"/>
                                           </PathFigure>
                                       </PathGeometry>
                                   </Path.Data>
                               </Path>
                           </Canvas>

<Canvas x:Name="dizuo" Width="80" Height="100" Canvas.Top="200" Canvas.Left="60">
                               <Path  Stroke="#030303" Fill="#A1A7BE" >
                                   <Path.Data>
                                       <PathGeometry>
                                           <PathFigure StartPoint="0 0" IsClosed="True">
                                               <LineSegment Point="20 0"/>
                                               <LineSegment Point="20 92"/>
                                               <LineSegment Point="0 92"/>
                                           </PathFigure>
                                           <PathFigure StartPoint="0 92" IsClosed="True">
                                               <LineSegment Point="12 92"/>
                                               <LineSegment Point="12 100"/>
                                               <LineSegment Point="0 100"/>
                                           </PathFigure>
                                       </PathGeometry>
                                   </Path.Data>
                               </Path>
                               <Path  Stroke="#030303" Fill="#7A7E90"  Canvas.Left="20">
                                   <Path.Data>
                                       <PathGeometry>
                                           <PathFigure StartPoint="0 0" IsClosed="True">
                                               <LineSegment Point="40 0"/>
                                               <LineSegment Point="40 92"/>
                                               <LineSegment Point="0 92"/>
                                           </PathFigure>
                                           <PathFigure StartPoint="0 92" IsClosed="True">
                                               <LineSegment Point="-8 92"/>
                                               <LineSegment Point="-8 100"/>
                                               <LineSegment Point="48 100"/>
                                               <LineSegment Point="48 92"/>
                                           </PathFigure>
                                       </PathGeometry>
                                   </Path.Data>
                               </Path>
                               <Path  Stroke="#030303" Fill="#585368" Canvas.Left="60">
                                   <Path.Data>
                                       <PathGeometry>
                                           <PathFigure StartPoint="0 0" IsClosed="True">
                                               <LineSegment Point="20 0"/>
                                               <LineSegment Point="20 92"/>
                                               <LineSegment Point="0 92"/>
                                           </PathFigure>
                                           <PathFigure StartPoint="8 92" IsClosed="True">
                                               <LineSegment Point="20 92"/>
                                               <LineSegment Point="20 100"/>
                                               <LineSegment Point="8 100"/>
                                           </PathFigure>
                                       </PathGeometry>
                                   </Path.Data>
                               </Path>
                           </Canvas>

<Canvas x:Name="robot" Width="100" Height="150" RenderTransformOrigin="1 1" >
                               <Canvas.RenderTransform>
                                   <TransformGroup>
                                       <RotateTransform  x:Name="robotRotateAct"/>
                                       <TranslateTransform  x:Name="robotUpDownAct"></TranslateTransform>
                                   </TransformGroup>
                               </Canvas.RenderTransform>
                               <Canvas x:Name="armXT1" Width="200" Height="100"  Canvas.Top="100" RenderTransformOrigin="0.5 0.5">
                                   <Canvas.RenderTransform>
                                       <RotateTransform  x:Name="armXT1RotateAct"/>
                                   </Canvas.RenderTransform>

<Canvas x:Name="armXT1Arm" Width="70" Height="30"  Canvas.Left="30" Canvas.Top="35" RenderTransformOrigin="1 0.5">
                                       <Path  Stroke="{StaticResource robotBorderBrush}" Fill="#FF7F50" StrokeThickness="1" StrokeEndLineCap="Round" >
                                           <Path.Data>
                                               <PathGeometry>
                                                   <PathFigure StartPoint="0 5" IsClosed="True">
                                                       <LineSegment Point="51 0"/>
                                                       <LineSegment Point="51 30" IsStroked="False"/>
                                                       <LineSegment Point="0 25"/>
                                                       <LineSegment Point="0 5" IsStroked="False"/>
                                                   </PathFigure>
                                               </PathGeometry>
                                           </Path.Data>
                                       </Path>
                                       <Path Stroke="{StaticResource robotBorderBrush}" StrokeThickness="1" Canvas.Left="0"
                                               StrokeEndLineCap="Round" StrokeStartLineCap="Round" Fill="#FF7F50"
                                               Data="M 0,5 A 10,10 0 0 0 0,25">
                                       </Path>
                                   </Canvas>

<Canvas x:Name="armXT1Center"  Width="40" Height="40" Canvas.Left="80" Canvas.Top="30" >
                                       <Path  Stroke="{StaticResource robotBorderBrush}"  Fill="#FF7F50" StrokeThickness="1" StrokeEndLineCap="Round"  >
                                           <Path.Data>
                                               <PathGeometry>
                                                   <PathFigure StartPoint="0 6" IsClosed="True">
                                                       <LineSegment Point="6 0"/>
                                                       <LineSegment Point="34 0"/>
                                                       <LineSegment Point="40 6"/>
                                                       <LineSegment Point="40 34"/>
                                                       <LineSegment Point="34 40"/>
                                                       <LineSegment Point="6 40"/>
                                                       <LineSegment Point="0 34"/>
                                                   </PathFigure>
                                               </PathGeometry>
                                           </Path.Data>
                                       </Path>
                                   </Canvas>
                               </Canvas>

<Canvas x:Name="armXT2" Width="120" Height="40" Canvas.Left="-90" Canvas.Top="130">
                                   <Canvas.RenderTransform>
                                       <TransformGroup>
                                           <TranslateTransform x:Name="armXT2Act"></TranslateTransform>
                                       </TransformGroup>
                                   </Canvas.RenderTransform>
                                   <Canvas x:Name="armXT2Arm" Width="70" Height="20"  Canvas.Left="50" Canvas.Top="10" RenderTransformOrigin="0 0.5" Background="#6495ED">
                                       <Canvas.RenderTransform>
                                           <RotateTransform x:Name="armXT2ArmRotateAct"/>
                                       </Canvas.RenderTransform>
                                       <Path Stroke="{StaticResource robotBorderBrush}" StrokeThickness="1" Canvas.Left="70"
                                       StrokeEndLineCap="Round" StrokeStartLineCap="Round" Fill="#6495ED"
                                       Data="M 0,0 A 10,10 0 0 1 0,20">
                                       </Path>
                                       <Path Stroke="{StaticResource robotBorderBrush}" StrokeThickness="1" Canvas.Left="0"
                                       StrokeEndLineCap="Round" StrokeStartLineCap="Round" Fill="#6495ED"
                                       Data="M 0,0 A 10,10 0 0 0 0,20">
                                       </Path>

<Path  Stroke="{StaticResource robotBorderBrush}" Fill="#6495ED" StrokeThickness="1" StrokeEndLineCap="Round" >
                                           <Path.Data>
                                               <PathGeometry>
                                                   <PathFigure StartPoint="70 0" >
                                                       <LineSegment Point="0 0" />
                                                       <LineSegment Point="0 20" IsStroked="False"/>
                                                       <LineSegment Point="70 20"/>
                                                       <LineSegment Point="70 0" IsStroked="False"/>
                                                   </PathFigure>
                                               </PathGeometry>
                                           </Path.Data>
                                       </Path>
                                       <Ellipse Width="12" Height="12" Stroke="#030303" StrokeThickness="2"  Fill="Transparent"
                                            Canvas.Top="4" Canvas.Left="62"/>
                                   </Canvas>

<Canvas x:Name="armGripper" Height="40" Width="50"  Canvas.Left="0" Canvas.Top="0">
                                       <Path  Stroke="{StaticResource robotBorderBrush}"  StrokeThickness="2" StrokeEndLineCap="Round" >
                                           <Path.Data>
                                               <PathGeometry>
                                                   <PathFigure StartPoint="30 14" >
                                                       <LineSegment Point="10 14" />
                                                       <LineSegment Point="4 8" />
                                                       <LineSegment Point="-6 8" />
                                                   </PathFigure>

<PathFigure StartPoint="30 26" >
                                                       <LineSegment Point="10 26" />
                                                       <LineSegment Point="4 32" />
                                                       <LineSegment Point="-6 32" />
                                                   </PathFigure>
                                               </PathGeometry>
                                           </Path.Data>
                                       </Path>
                                       <Path  Stroke="{StaticResource robotBorderBrush}" Fill="#7A7E90"  StrokeThickness="1" StrokeEndLineCap="Round" >
                                           <Path.Data>
                                               <PathGeometry>
                                                   <PathFigure StartPoint="40 0" >
                                                       <LineSegment Point="60 0" />
                                                       <LineSegment Point="60 40" />
                                                       <LineSegment Point="40 40" />
                                                       <LineSegment Point="30 30" />
                                                       <LineSegment Point="30 10" />
                                                       <LineSegment Point="40 0" />
                                                   </PathFigure>
                                               </PathGeometry>
                                           </Path.Data>
                                       </Path>
                                       <Path  Stroke="{StaticResource robotBorderBrush}" Fill="#7A7E90" StrokeThickness="1" StrokeEndLineCap="Round" >
                                           <Path.Data>
                                               <PathGeometry>
                                                   <PathFigure StartPoint="30 10" >
                                                       <LineSegment Point="20 10" />
                                                       <LineSegment Point="20 30" />
                                                       <LineSegment Point="30 30" />
                                                       <LineSegment Point="30 10" IsStroked="False"/>
                                                   </PathFigure>
                                               </PathGeometry>
                                           </Path.Data>
                                       </Path>

<Ellipse Width="12" Height="12" Stroke="#030303" StrokeThickness="2"  Fill="Transparent"
                                            Canvas.Top="14" Canvas.Left="44"/>
                                       <Ellipse x:Name="wafer" Width="40" Height="40" StrokeThickness="1" Stroke="Black"  Canvas.Left="-24"
                                                Visibility="{Binding Wafer,Converter={StaticResource WaferIntToVisibilityConverter},
                                                   RelativeSource={RelativeSource TemplatedParent}}"
                                                Fill="{Binding Wafer,Converter={StaticResource WaferIntToColorConverter},
                                                    RelativeSource={RelativeSource TemplatedParent}}"/>
                                   </Canvas>
                               </Canvas>
                           </Canvas>
                       </Canvas>
                   </Viewbox>
               </ControlTemplate>
           </Setter.Value>
       </Setter>
</Style>

四 效果演示

界面代码如下:

<Window x:Class="WpfApp1.MainWindow"
       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:wpfapp1="clr-namespace:WpfApp1"
       mc:Ignorable="d" Background="WhiteSmoke"
       Title="MainWindow" Height="800" Width="1200">
   <Canvas>
       <wpfapp1:WaferRobotControl Canvas.Left="472" Canvas.Top="171" x:Name="robot"/>
       <Button Content="Z CW" Canvas.Left="757" Canvas.Top="338" Width="60" Height="30" Click="ZCWButton_Click"   />
       <Button Content="Z CCW" Canvas.Left="757" Canvas.Top="388" Width="60" Height="30" Click="ZCCWButton_Click"/>
       <Button Content="X CW" Canvas.Left="838" Canvas.Top="338" Width="60" Height="30" Click="XCWButton_Click"/>
       <Button Content="X CCW" Canvas.Left="838" Canvas.Top="389" Width="60" Height="30" Click="XCCWButton_Click"/>
       <Button Content="T CW" Canvas.Left="919" Canvas.Top="338" Width="60" Height="30" Click="TCWButton_Click"/>
       <Button Content="T CCW" Canvas.Left="919" Canvas.Top="389" Width="60" Height="30" Click="TCCWButton_Click"/>
       <Button Content="Auto" Canvas.Left="757" Canvas.Top="439" Width="60" Height="30" Click="AutoButton_Click"/>
   </Canvas>
</Window>

后台代码如下:

public partial class MainWindow : Window
   {
       public MainWindow()
       {
           InitializeComponent();
       }

private void ZCWButton_Click(object sender, RoutedEventArgs e)
       {
           robot.RobotZAction = WaferRobotZAction.Z_CW;
       }

private void ZCCWButton_Click(object sender, RoutedEventArgs e)
       {
           robot.RobotZAction = WaferRobotZAction.Z_CCW;
       }

private void XCWButton_Click(object sender, RoutedEventArgs e)
       {
           robot.RobotXAction = WaferRobotXAction.X_CW;
       }

private void XCCWButton_Click(object sender, RoutedEventArgs e)
       {
           robot.RobotXAction = WaferRobotXAction.X_CCW;
       }

private void TCWButton_Click(object sender, RoutedEventArgs e)
       {
           robot.RobotTAction = WaferRobotTAction.T_CW;
       }

private void TCCWButton_Click(object sender, RoutedEventArgs e)
       {
           robot.RobotTAction = WaferRobotTAction.T_CCW;
       }

private void AutoButton_Click(object sender, RoutedEventArgs e)
       {
           Task.Run(async () =>
           {
               Application.Current.Dispatcher?.Invoke
               (
                  () => { this.robot.RobotTAction = WaferRobotTAction.T_CCW; }
               );
               await Task.Delay(1000);

Application.Current.Dispatcher?.Invoke
               (
                  () => { this.robot.RobotXAction = WaferRobotXAction.X_CW; }
               );
               await Task.Delay(2000);

Application.Current.Dispatcher?.Invoke(
                   () => { this.robot.Wafer = 1; }
                   );
               await Task.Delay(200);

Application.Current.Dispatcher?.Invoke(
                  () => { this.robot.RobotXAction = WaferRobotXAction.X_CCW; }
                  );
               await Task.Delay(2000);

Application.Current.Dispatcher?.Invoke(
                () => { this.robot.RobotZAction = WaferRobotZAction.Z_CW; }
                );
               await Task.Delay(1000);

Application.Current.Dispatcher?.Invoke
               (
                  () => { this.robot.RobotTAction = WaferRobotTAction.T_CW; }
               );
               await Task.Delay(1000);

Application.Current.Dispatcher?.Invoke
               (
                () => { this.robot.RobotXAction = WaferRobotXAction.X_CW; }
               );
               await Task.Delay(2000);

Application.Current.Dispatcher?.Invoke(
                   () => { this.robot.Wafer = 0; }
                   );
               await Task.Delay(200);

Application.Current.Dispatcher?.Invoke(
                () => { this.robot.RobotXAction = WaferRobotXAction.X_CCW; }
                );
               await Task.Delay(2000);
               Application.Current.Dispatcher?.Invoke
               (
                 () => { this.robot.RobotTAction = WaferRobotTAction.T_Origin; }
               );
               await Task.Delay(1000);
               Application.Current.Dispatcher?.Invoke
               (
                 () => { this.robot.RobotZAction = WaferRobotZAction.Z_CCW; }
               );
               await Task.Delay(1000);
           });
       }
   }

来源:https://www.cnblogs.com/wwwen/p/17076289.html

标签:WPF,三轴机械手,控件
0
投稿

猜你喜欢

  • 全面解析Android之ANR日志

    2023-12-18 23:30:21
  • C# 获取PDF中的数字签名证书

    2023-03-07 18:16:15
  • mybatis in查询条件过长的解决方案

    2022-06-08 12:44:14
  • Android开发之ProgressBar字体随着进度条的加载而滚动

    2023-12-28 03:06:53
  • C#实现在PDF文档中应用多种不同字体

    2022-01-18 02:13:28
  • C# Stream 和 byte[] 之间的转换

    2023-06-24 23:14:52
  • @TransactionalEventListener的使用和实现原理分析

    2022-01-19 06:15:11
  • C#通过创建Windows服务启动程序的方法详解

    2022-09-16 15:32:49
  • android 引导界面的实现方法

    2023-08-07 04:58:11
  • Android实现自定义圆形进度条

    2022-10-28 04:55:22
  • 仅4行代码实现Android快速文件下载

    2022-08-14 08:06:54
  • JavaSE static final及abstract修饰符实例解析

    2021-07-01 10:54:54
  • 两路归并的数组与链表的实现方法

    2021-10-28 04:32:15
  • Java实现复制文件并命名的超简洁写法

    2022-02-12 12:54:06
  • Java 判断字符为中文实例代码(超管用)

    2021-08-24 13:18:31
  • C# FileStream实现多线程断点续传

    2022-06-19 06:50:56
  • java设计模式之外观模式学习笔记

    2022-07-02 18:48:06
  • Java反射获取实例的速度对比分析

    2021-06-14 09:22:29
  • java解析Excel的方法(xls、xlsx两种格式)

    2021-10-12 16:29:39
  • C#9特性record 类型、模式匹配、init 属性详情

    2023-07-09 04:48:25
  • asp之家 软件编程 m.aspxhome.com