X1,Y1作为起点,X2,Y2作为终点。Stroke(边线)属性的数据类型是Brush,用来填充。
<Window x:Class="WpfApplication1.Window45"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window45" Height="293" Width="437">
<Line X1="10" Y1="20" X2="260" Y2="20" Stroke="Red" StrokeThickness="10"></Line>
<Line X1="10" Y1="40" X2="260" Y2="40" Stroke="Orange" StrokeThickness="6"></Line>
<Line X1="10" Y1="60" X2="260" Y2="60" Stroke="Green" StrokeThickness="3"></Line>
<Line X1="10" Y1="80" X2="260" Y2="80" Stroke="Purple" StrokeThickness="2"></Line>
<Line X1="10" Y1="100" X2="260" Y2="100" Stroke="Black" StrokeThickness="1"></Line>
<Line X1="10" Y1="120" X2="260" Y2="120" StrokeDashArray="3" Stroke="Black" StrokeThickness="1"></Line>
<Line X1="10" Y1="140" X2="260" Y2="140" StrokeDashArray="5" Stroke="Black" StrokeThickness="1"></Line>
<Line X1="10" X2="260" Y1="160" Y2="160" Stroke="Black" StrokeThickness="6" StrokeEndLineCap="Flat"></Line>
<Line X1="10" X2="260" Y1="180" Y2="180" Stroke="Black" StrokeThickness="8" StrokeEndLineCap="Triangle"></Line>
<Line X1="10" X2="260" Y1="200" Y2="200" StrokeEndLineCap="Round" StrokeThickness="10">
<Line.Stroke>
<LinearGradientBrush EndPoint="0,0.5" StartPoint="1,0.5">
<GradientStop Color="Blue"></GradientStop>
<GradientStop Offset="1" Color="Red"></GradientStop>
</LinearGradientBrush>
</Line.Stroke>
</Line>
</Grid>
</Window>
矩形由Stroke(边线)和Fill(填充)构成。数据类型均为Brush,常见的Brush子类有:
SolidColorBrush:实心画刷,常用Red、Blue等字符串赋值
LinearGradientBrush:线性渐变画刷
RadialGradentBrush:径向渐变画刷
ImageBrush:图片作为内容
DrawingBrush:矢量图或者位图填充
VisualBrush:每个控件的可视化形象可以通过Visual类的方法获得,并用该形象进行填充,这就是VisualBrush。如:控件被拖拽过程中显示一个幻影,这个幻影就可以使用VisualBrush来填充。
<Window x:Class="WpfApplication1.Window46"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window46" Height="390" Width="600">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="180" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="180*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="160" />
<RowDefinition Height="10" />
<RowDefinition Height="160" />
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Grid.Column="0" Stroke="Black" Fill="LightBlue"></Rectangle>
<Rectangle Grid.Row="0" Grid.Column="2">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#FFB6F8F1" Offset="0"></GradientStop>
<GradientStop Color="#FF0082BD" Offset="0.25"></GradientStop>
<GradientStop Color="#FF95DEFF" Offset="0.6"></GradientStop>
<GradientStop Color="#FF004F72" Offset="1"></GradientStop>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="0" Grid.Column="4">
<Rectangle.Fill>
<RadialGradientBrush>
<GradientStop Color="#FFB6F8F1" Offset="0"></GradientStop>
<GradientStop Color="#FF0082BD" Offset="0.25"></GradientStop>
<GradientStop Color="#FF95DEFF" Offset="0.75"></GradientStop>
<GradientStop Color="#FF004F72" Offset="1.5"></GradientStop>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="2" Grid.Column="0">
<Rectangle.Fill>
<ImageBrush ImageSource="./01077_1.png" Viewport="0,0,0.3,0.3" TileMode="Tile">
</ImageBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="2" Grid.Column="2">
<Rectangle.Fill>
<DrawingBrush Viewport="0,0,0.2,0.2" TileMode="Tile">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="LightBlue">
<GeometryDrawing.Geometry>
<EllipseGeometry RadiusX="10" RadiusY="10"></EllipseGeometry>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="2" Grid.Column="5" StrokeThickness="10">
<Rectangle.Stroke>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="White" Offset="0.3"></GradientStop>
<GradientStop Color="Blue" Offset="1"></GradientStop>
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
</Grid>
</Window>
使用visualBrush的案例
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="160" />
</Grid.ColumnDefinitions>
<StackPanel Background="White" x:Name="spleft">
<Button Height="40" Content="OK" x:Name="btnReal" Click="btnReal_Click"></Button>
</StackPanel>
<Button Grid.Column="1" Content=">>" Margin="5,0"></Button>
<StackPanel Grid.Column="2" Background="White" x:Name="spRight">
</StackPanel>
</Grid>
double o = 1;
private void btnReal_Click(object sender, RoutedEventArgs e)
VisualBrush vb = new VisualBrush(this.btnReal);
Rectangle rtg = new Rectangle();
rtg.Width = btnReal.Width;
rtg.Height = btnReal.Height;
rtg.Fill = vb;
rtg.Opacity = o;
o -= 0.2;
this.spRight.Children.Add(rtg);
<Ellipse Height="140" Name="ellipse1" Stroke="Gray" Width="140" Cursor="Hand" ToolTip="A Ball">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.2,0.8" RadiusX="0.75" RadiusY="0.75">
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<RotateTransform Angle="90" CenterX="0.5" CenterY="0.5"></RotateTransform>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="#FFFFFFFF" Offset="0" />
<GradientStop Color="#FF444444" Offset="0.66" />
<GradientStop Color="#FF999999" Offset="1" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
</Grid>
路径可以替代其他几种图形,并且可以将直线、圆弧等基本元素结合形成复杂的图形。Path最重要的属性是Data,其数据类型为Geometry抽象类。Geometry子类包括:
LineGeometry:直线几何
RectangleGeometry:矩形几何
EllipseGeometry:椭圆几何
PathGeometry:路径几何
StreamGeometry:PathGeometry的轻量替代类,不支持Binding、动画等
CombinedGeometry:多个基本图形的组合,形成一个几何图形
GeometryGroup:多个基本图形的组合,形成一个几何图形组
与Line、Rectangle等的区别:Line等可以独立存在,而Geometry只能结合其他几何,不能独立存在。
<Grid.RowDefinitions>
<RowDefinition Height="160" />
<RowDefinition Height="160" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160" />
<ColumnDefinition Width="160" />
</Grid.ColumnDefinitions>
<Path Stroke="Blue" StrokeThickness="2" Grid.Row="0" Grid.Column="0">
<Path.Data>
<LineGeometry StartPoint="0,0" EndPoint="160,160"></LineGeometry>
</Path.Data>
</Path>
<Path Stroke="Orange" Fill="Yellow" Grid.Row="0" Grid.Column="1">
<Path.Data>
<RectangleGeometry Rect="20,20,120,120" RadiusX="10" RadiusY="10"></RectangleGeometry>
</Path.Data>
</Path>
<Path Stroke="Green" Fill="LawnGreen" Grid.Column="0" Grid.Row="1">
<Path.Data>
<EllipseGeometry Center="80,80" RadiusX="60" RadiusY="40"></EllipseGeometry>
</Path.Data>
</Path>
<Path Stroke="Yellow" Fill="Orange" Grid.Row="1" Grid.Column="1">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="25,140" IsClosed="True">
<PathFigure.Segments>
<LineSegment Point="20,40"></LineSegment>
<LineSegment Point="40,110"></LineSegment>
<LineSegment Point="50,20"></LineSegment>
<LineSegment Point="80,110"></LineSegment>
<LineSegment Point="110,20"></LineSegment>
<LineSegment Point="120,110"></LineSegment>
<LineSegment Point="140,40"></LineSegment>
<LineSegment Point="135,140"></LineSegment>
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Grid>
PathFigure的Segments属性所包含的线段:
LineSegment:直线
ArcSegment:圆弧
BezierSement:三次方贝塞尔曲线
QuadraticBezierSement:二次方贝塞尔曲线
PolyLineSegment:多直线段
PolyBezierSegment:多三次方贝塞尔曲线
PolyQuadraticBezierSement:多二次方贝塞尔曲线
注意:绘制上面的线段是没有起点的,起点就是上一个线段的终点,第一个线段的起点是PathFigure的StartPoint。
Path非常强大,但是上面的标签式的语法过于繁琐。WPF提供路径标记法来替代标签式语法。、
路径标记法就是各种线段的简记法,如<LineSegment Point="15,15">
可以改为L, 15,15
。除此之外,路径标记法还增加了一些实用的命令,如H 80
,代表从当前点画一条水平直线,横坐标终点是80。
使用路径标记法的步骤分为三步移动至起点->绘图->闭合图形
,常用命令如下:
命令 | 用途 | 语法 | 示例 | 标签式语法 | 分类 |
---|
M | 移动到起点 | M 起始点 | M 10,10 | | 移动命令 |
L | 绘制直线 | L 终点 | L 150,30 | | 绘图命令 |
H | 绘制水平直线 | H 终点横坐标 | H 180 | | 绘图命令 |
V | 绘制数值线 | V 终点纵坐标 | V 180 | | 绘图命令 |
A | 绘制圆弧 | A 母椭圆尺寸 旋转角度是否大弧 顺/逆 终点 | A 180,80 45 1 1 150,150 | | 绘图命令 |
C | 三次方贝塞尔曲线 | C 控制点1 控制点2 终点 | C 250,0 50,200 300,200 | | 绘图命令 |
Q | 二次方贝塞尔 | Q 控制点1 终点 | Q 150,100 300,200 | | 绘图命令 |
S | 平滑三次贝塞尔 | S 控制点2 终点 | S 100,200 200,300 | | 绘图命令 |
T | 平滑二次方贝塞尔 | T 终点 | T 400,200 | | 绘图命令 |
Z | 闭合图形 | Z | M 0,0 L 40,80 L80,40 Z | | 关闭命令 |
不规则窗体和控件仅需使用Clip属性就可以做到。
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<Path Stroke="Orange" Fill="Yellow" x:Name="clipPath0" Visibility="Hidden" Data="M 55,100 A 50,50 0 1 1 100,60 A 110,95 0 0 1 200,60 A 50,50 0 1 1 250,100 A 110,95 0 1 1 55,100 Z">
</Path>
<Button Content="Clip" Width="80" Height="25" Click="Button_Click" HorizontalAlignment="Center" VerticalAlignment="Center"></Button>
</Grid>
private void Button_Click(object sender, RoutedEventArgs e)
this.Clip = clipPath0.Data;
WPF早期的效果属性,是使用CPU来进行运算,会导致程序卡顿,不建议使用
BitmapEffect派生类:
BevelBitmapEffect:斜角效果
BitmapEffectGroup:符合效果
BlurBitmapEffect:模糊效果
DropShadowBitmapEffect:投影效果
EmbossBitmapEffect:浮雕效果
OuterGlowBitmapEffect:外发光效果
<Button Content="Click Me" Grid.Column="0" Grid.Row="0" Margin="20">
<Button.BitmapEffect>
<BlurBitmapEffect Radius="3"/>
</Button.BitmapEffect>
</Button>
采用GPU对UI进行渲染,功能强大。
Effect具有如下派生类
BlurEffect:模糊效果
DropShadowEffect:投影效果
ShaderEffect:着色器(抽象类)
WPF中的变形与UI元素是分开的,可以单独设置一个旋转45度的变形,然后把该变形赋值给不同的UI元素。
控制变形的属性有两个:
RenderTransform:呈现变形
LayoutTransform:布局变形
这两个属性的值类型为Transform抽象类型,常见的派生类有:
MatrixTransform:矩阵变形
RotateTransform:旋转变形
ScaleTransform:缩放变形
SkewTransform:拉伸变形
TranslateTransform:偏移变形
TransformGroup:变形组
让UI元素呈现出来的属性与本来的属性不一样,如按钮本来在左上角,但是让他呈现在右下角,且旋转45度。
<Window x:Class="WpfApplication1.Window59"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window59" Height="334" Width="485">
<Grid Margin="10" Background="AliceBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto">
</ColumnDefinition>
<ColumnDefinition Width="*">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto">
</RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button Width="80" Height="80" Content="OK" Background="Red" Foreground="White">
<Button.RenderTransform>
<TransformGroup>
<RotateTransform CenterX="40" CenterY="40" Angle="45"></RotateTransform>
<TranslateTransform X="300" Y="150"></TranslateTransform>
</TransformGroup>
</Button.RenderTransform>
</Button>
</Grid>
</Window>
在Grid中划分了2行2列,第一行第一列根据Button自动调整,然后利用变形天正button的位置和角度,但是Button本身的位置属性却没有改变,这样仅仅改变button的显示效果会极大提高效率。所以在做动画的时候一定要用Render Transform。
与呈现变形不同,布局变形会影响整个窗体的布局导致重新测算,所以会影响程序的性能。布局变形一般用在静态变形上。
实现文字纵向排列
使用呈现变形
<Grid x:Name="titleBar" Background="LightBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock FontSize="24" Text="Hello Transformer" VerticalAlignment="Bottom" HorizontalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"></RotateTransform>
</TextBlock.LayoutTransform>
</TextBlock>
</Grid>
看上去实现了纵向排列,但事实上TextBox本身属性没有变,所以Grid的第一列宽度任然没有变。
使用布局变形
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"></RotateTransform>
</TextBlock.LayoutTransform>
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"></RotateTransform>
</TextBlock.LayoutTransform>
此时,Grid的第一列宽度改变。
步_步_为营
软件开发工程师 @ 中核集团
粉丝