WPF基本的图形包括:
绘图不一定要在Canvas中完成,可以再任何一种布局中完成。
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">
<Grid>
<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>
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dv5lBODs-1668244504880)(C:\Users\cni23287938\AppData\Roaming\Typora\typora-user-images\image-20221111151636222.png)]](https://1000bd.com/contentImg/2024/04/24/75f548f4a8468ebc.png)
矩形由Stroke(边线)和Fill(填充)构成。数据类型均为Brush,常见的Brush子类有:
<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>
<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>
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-acj40m9h-1668244504881)(11.绘图.assets/image-20221111153230825.png)]](https://1000bd.com/contentImg/2024/04/24/f4e5bafb2ff87db2.png)
使用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);
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fuS3Exaf-1668244504881)(11.绘图.assets/image-20221111154534841.png)]](https://1000bd.com/contentImg/2024/04/24/b381979f47128034.png)
<Grid>
<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>
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-peioLCuy-1668244504882)(11.绘图.assets/image-20221111154656159.png)]](https://1000bd.com/contentImg/2024/04/24/a150e0ee038a4fb2.png)
路径可以替代其他几种图形,并且可以将直线、圆弧等基本元素结合形成复杂的图形。Path最重要的属性是Data,其数据类型为Geometry抽象类。Geometry子类包括:
与Line、Rectangle等的区别:Line等可以独立存在,而Geometry只能结合其他几何,不能独立存在。
<Grid>
<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属性所包含的线段:
注意:绘制上面的线段是没有起点的,起点就是上一个线段的终点,第一个线段的起点是PathFigure的StartPoint。
Path非常强大,但是上面的标签式的语法过于繁琐。WPF提供路径标记法来替代标签式语法。、
路径标记法就是各种线段的简记法,如可以改为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;
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uIIf142q-1668244504882)(11.绘图.assets/image-20221111165718454.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rFXmg5cL-1668244504883)(11.绘图.assets/image-20221111165800466.png)]](https://1000bd.com/contentImg/2024/04/24/182e4cf3e5c7cdbe.png)
WPF早期的效果属性,是使用CPU来进行运算,会导致程序卡顿,不建议使用
BitmapEffect派生类:
<Button Content="Click Me" Grid.Column="0" Grid.Row="0" Margin="20">
<Button.BitmapEffect>
<BlurBitmapEffect Radius="3"/>
Button.BitmapEffect>
Button>
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IAm7FxjF-1668244504883)(11.绘图.assets/image-20221112164221060.png)]](https://1000bd.com/contentImg/2024/04/24/3132f49cd1ea42bb.png)
采用GPU对UI进行渲染,功能强大。
Effect具有如下派生类
WPF中的变形与UI元素是分开的,可以单独设置一个旋转45度的变形,然后把该变形赋值给不同的UI元素。
控制变形的属性有两个:
这两个属性的值类型为Transform抽象类型,常见的派生类有:
让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>
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ynrVYjuf-1668244504884)(11.绘图.assets/image-20221112170224537.png)]](https://1000bd.com/contentImg/2024/04/24/5ea0f0e8024dac3f.png)
在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>
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p3CXShVD-1668244504884)(11.绘图.assets/image-20221112170931574.png)]](https://1000bd.com/contentImg/2024/04/24/fa08096efd94543a.png)
看上去实现了纵向排列,但事实上TextBox本身属性没有变,所以Grid的第一列宽度任然没有变。
将上面的
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90">RotateTransform>
TextBlock.LayoutTransform>
改为
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90">RotateTransform>
TextBlock.LayoutTransform>
此时,Grid的第一列宽度改变。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jd0b6Tf3-1668244504884)(11.绘图.assets/image-20221112171325173.png)]](https://1000bd.com/contentImg/2024/04/24/8847ca47f2582fb4.png)