Graphics 图形
您可以将图形元素与标记中的其他元素无缝混合。布局对图形的作用与对任何其他元素的作用完全相同。
图形和其他内容不仅可以在标记中并排存在,而且它们甚至可以混合在一起。
<TextBlock FontSize="24" TextWrapping="Wrap"> And of course you can put graphics into your text: <Ellipse Fill="Cyan" Width="50" Height="20" /> </TextBlock>
混合是双向的,你不仅可以将控件混合到图形中,还可以在控件中使用图形元素。
以下显示一个以混合文本和图形作为标题的按钮:
<StackPanel> <Button> <StackPanel Orientation="Horizontal"> <Canvas Width="20" Height="18" VerticalAlignment="Center"> <Ellipse Canvas.Left="1" Canvas.Top="1" Width="16" Height="16" Fill="Yellow" Stroke="Black"/> <Ellipse Canvas.Left="4.5" Canvas.Top="5" Width="2.5" Height="3" Fill="Black"/> <Ellipse Canvas.Left="11" Canvas.Top="5" Width="2.5" Height="3" Fill="Black"/> <Path Data="M 5,10 A 3,3 0 0 0 13,10" Stroke="Black" /> </Canvas> <TextBlock VerticalAlignment="Center">Click!</TextBlock> </StackPanel> </Button> <Button HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Ellipse Grid.Column="0" Grid.Row="0" Fill="Yellow" Width="10" Height="10" /> <Ellipse Grid.Column="2" Grid.Row="0" Fill="Red" Width="10" Height="10" /> <Ellipse Grid.Column="0" Grid.Row="2" Fill="Blue" Width="10" Height="10" /> <Ellipse Grid.Column="2" Grid.Row="2" Fill="Blue" Width="10" Height="10" /> <Ellipse Grid.ColumnSpan="3" Grid.RowSpan="3" Stroke="LightGreen" StrokeThickness="3" /> <TextBlock Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Text="Click!" /> </Grid> </Button> </StackPanel>
您可以将表示图形形状的对象添加到用户界面元素树中。形状元素是 UI 树中的对象,与其他任何对象一样,因此您的代码可以随时修改它们。如果您更改某些具有视觉影响的属性(例如大小、位置或颜色),WPF 将自动更新显示。
<Canvas x:Name="mainCanvas"> <Ellipse Canvas.Left="10" Canvas.Top="30" Fill="Indigo" Width="40" Height="20" /> <Ellipse Canvas.Left="20" Canvas.Top="40" Fill="Blue" Width="40" Height="20" /> <Ellipse Canvas.Left="30" Canvas.Top="50" Fill="Cyan" Width="40" Height="20" /> <Ellipse Canvas.Left="40" Canvas.Top="60" Fill="LightGreen" Width="40" Height="20" /> <Ellipse Canvas.Left="50" Canvas.Top="70" Fill="Yellow" Width="40" Height="20" /> </Canvas>
public partial class MainWindow : Window { public MainWindow(IRegionManager regionManager) { InitializeComponent(); mainCanvas.MouseLeftButtonDown += MainCanvas_MouseLeftButtonDown; } private void MainCanvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { Ellipse r = e.Source as Ellipse; if (r!=null) { r.Width += 10; } } }
“可视化层编程”
部分描述了按需渲染机制。同样在本章后面的“DrawingBrush”部分描述了介于 两者之间的第三种技术,它牺牲了一点灵活性以撚取更好的性能,它提供了保留模型的许多好处,但没有开销一个完整的WPF框架元素。
Scaling and rotation 缩放和旋转
<Button> <Button.LayoutTransform> <ScaleTransform ScaleX="3" ScaleY="3" /> </Button.LayoutTransform> ... as before ... </Button>
形状、画笔和钢笔
WPF 绘图工具包中的大多数类都属于以下三个类别之一:形状、画笔和钢笔
形状是用户界面树中的对象,为绘图提供基本构建块。我们已经看到的Ellipse、 Path和Rectangle元素都是形状对象的示例。还支持分别使用Line和Polyline的单段和多段线。多边形创建闭合的形
状,其边缘都是直的。 Path类支持开放和封闭的形状,可以任意混合直边和曲边。
无论您选择哪种形状,您都需要决定应该如何着色。为此,您需要使用画笔。许多画笔类型可用。最简单的是单色SolidColorBrush。您可以使用LinearGradientBrush或RadialGradientBrush实
现更有趣的视觉效果。这些允许颜色在形状的表面上发生变化,这是提供深度印象的好方法。
您还 可以基于图像创建画笔 ImageBrush 使用位图,而 DrawingBrush 使用可绽放绘图。
最后,用钢笔画出形状的轮廓。钢笔实际上只是一个增强的画笔。当你创建一个Pen对象时,你给它一个Brush来告诉它应该如何在屏幕上绘画。 Pen类仅添加线条粗细、破折号图案和端盖细节等信息。
Shapes 形状
System.Windows.Shapes命名空间定义了在用户界面树中充当元素的绘图基元。 WPF 支持多种不同的形状,并为每种形状提供了元素类型
Ellipse
|
椭圆
|
Line
|
一条直线
|
Path
|
使用直线和曲线的任意组合的形状
|
Polygon
|
由直线组成的闭合形状
|
Polyline
|
由直线组成的开放形状
|
Rectangle
|
一个矩形,可选择带有圆角
|
形状对象与几何图形学习 WPF 的人的一个常见混淆来源是它似乎有两组图形类。例如,除了Rectangle,还有RectangleGeometry,我们有Path和PathGeometry。 System.Windows.Shapes命名空间中的大多数形状类在System.Windows.Media命名空间中都有相应的几何类。
如果需要布局、数据绑定或其它形状框架功能,请使用Shape 派生的类。如果你要用几个静态形状构建图片,几何图形和绘图可能是更好的选择。
Base Shape Class 基本形状类
本节中描述的所有元素都派生自一个公共抽象基类Shape。 Shape定义了一组可用于所有形状
的通用特征。
这些共同属性主要与绘制形状内部和轮廓的方式有关。
Fill属性指定将用于绘制内部的Brush 。 ( Line类没有内部,所以它忽略了这个属性。这比通过具有单独的Shape和FilledShape基类来复杂化继承层次结构更简单。) Stroke属性指定将用于
绘制的Brush形状的线条。
注意:如果您没有为形状指定Fill或Stroke ,它将不可见,因为默认情况下这两个属性都是空的。
Stroke属性属于Brush类型, WPF 实际上确实在内部使用 Pen 来绘制形状的轮廓。Stroke 属性属于Brush 类型主要是了为方便,所有Pen功能都通过Shape上的单独属性公开。这简化了你使用默认
画笔设置元素的场景,你不需要提供完整的画笔定义来设置轮廓颜色。
Shape Stroke 属性和 Pen 等效项
Shape property
|
Equivalent Pen property | ||
Stroke
|
Brush |
刷子
|
|
StrokeThickness
|
描边粗细
|
Thickness
|
厚度
|
StrokeLineJoin
|
描线连接
|
LineJoin
|
连线
|
StrokeMiterLimit
|
行程斜接限制
|
MiterLimit
|
斜接限制
|
StrokeDashArray
|
笔划破折号数组
|
DashArray
|
破折号数组
|
StrokeDashCap
|
DashCap
|
破折号
|
|
StrokeDashOffset
|
DashOffset
|
||
StrokeStartLineCap
|
描边起始线头
|
StartLineCap
|
起始线头
|
StrokeEndLineCap
|
笔划结束线帽
|
EndLineCap
|
端线帽
|
Shape类还定义了一个Stretch属性,该属性决定了在可用空间与其首选大小不匹配时如何调整形状
Uniform和UniformToFill在两个方向上的缩放比例相同。前者缩放直到形状在至少一个维度上足够大以填充可用空间,但如果需要,会在另一个维度上留下空闲空间以避免裁剪。
后者缩放形状直到它大到足以完全填满两个维度的空间,即使这意味着裁剪一个维度
注意:矩形和椭圆默认为拉伸填充,而其他形状都默认为无。
从Shape派生的类都添加了特定于它们所表示的形状类型的属性。所以,我们现在将看看这些类型中的每一种,从Rectangle 开始。
Rectangle
Rectangle顾名思义。与任何形状一样,它可以绘制为填充、轮廓,或同时填充和轮廓。除了绘制普通矩形外,它还可以绘制带圆角的矩形。
Rectangle不提供任何用于设置其位置的属性。它依赖于与任何其他 UI 元素相同的布局机制。该位置由包含面板确定。宽度和高度可以由父级自动设置,也可以使用标准布局属性Width和Height 显式设置。
<Canvas> <Rectangle Fill="Yellow" Stroke="Black" Canvas.Left="30" Canvas.Top="10" Width="100" Height="20"/> </Canvas>
Rectangle通常会与其父面板的坐标系对齐。这意味着它的边缘通常是水平和垂直的,尽管如果父面板已经旋转, Rectangle当然会随之旋转。
如果要相对于包含它的面板旋转一个Rectangle ,可以使用所有用户界面元素上可用的RenderTransform属性
<Canvas> <Rectangle Canvas.Left="50" Canvas.Top="50" Width="40" Height="10" Fill="Indigo" /> <Rectangle Canvas.Left="50" Canvas.Top="50" Width="40" Height="10" Fill="Violet"> <Rectangle.RenderTransform> <RotateTransform Angle="45" /> </Rectangle.RenderTransform> </Rectangle> <Rectangle Canvas.Left="50" Canvas.Top="50" Width="40" Height="10" Fill="Blue"> <Rectangle.RenderTransform> <RotateTransform Angle="90" /> </Rectangle.RenderTransform> </Rectangle> <Rectangle Canvas.Left="50" Canvas.Top="50" Width="40" Height="10" Fill="Cyan"> <Rectangle.RenderTransform> <RotateTransform Angle="135" /> </Rectangle.RenderTransform> </Rectangle> <Rectangle Canvas.Left="50" Canvas.Top="50" Width="40" Height="10" Fill="Green"> <Rectangle.RenderTransform> <RotateTransform Angle="180" /> </Rectangle.RenderTransform> </Rectangle> <Rectangle Canvas.Left="50" Canvas.Top="50" Width="40" Height="10" Fill="Yellow"> <Rectangle.RenderTransform> <RotateTransform Angle="225" /> </Rectangle.RenderTransform> </Rectangle> <Rectangle Canvas.Left="50" Canvas.Top="50" Width="40" Height="10" Fill="Orange"> <Rectangle.RenderTransform> <RotateTransform Angle="270" /> </Rectangle.RenderTransform> </Rectangle> <Rectangle Canvas.Left="50" Canvas.Top="50" Width="40" Height="10" Fill="Red"> <Rectangle.RenderTransform> <RotateTransform Angle="315" /> </Rectangle.RenderTransform> </Rectangle> </Canvas>
绘制带圆角的矩形,请使用RadiusX和RadiusY属性
<Rectangle Width="100" Height="50" Stroke="Red" StrokeThickness="3" Fill="Yellow" RadiusX="30" RadiusY="20" />
Ellipse 椭圆
椭圆类似于矩形。显然,它绘制的是椭圆而不是矩形,但椭圆的大小、位置、旋转、填充和描边的控制方式与矩形完全相同
<Ellipse Width="100" Height="50" Fill="Yellow" Stroke="Black" />
Line 线
Line元素绘制一条从一点到另一点的直线。它有四个控制位置的属性: X1和Y1定义起点, X2和Y2确定终点。这些坐标相对于父面板选择定位线的位置。
(在 WPF 中,正 Y 表示向下,这与典型的数学图形不同。)第二个Line元素一直到顶部,因为它的Y2属性设置为0,再次说明线端点的坐标系是相对的到包含面板分配给Line的区域
<StackPanel Margin="0 20 0 0"> <TextBlock Background="LightGray">Foo</TextBlock> <Line Stroke="Green" X1="20" Y1="10" X2="100" Y2="40"/> <TextBlock Background="LightGray">Bar</TextBlock> <Line Stroke="Green" X1="0" Y1="10" X2="100" Y2="0"/> </StackPanel>
可以使用Stretch属性使Line随您的布局自动调整大小。
<Line Stroke="Black" X1="0" X2="1" Stretch="Fill" />
Polyline 折线
折线可让您绘制一系列相连的线段。 Polyline没有起点和终点的属性,而是有一个Points属性,它包含一个坐标对列表
<Polyline Stroke="Blue" Points="0,30 10,30 15,0 18,60 23,30 35,30 40,0 43,60 48,30 160,30"/>
与Line类一样, Polyline中的点坐标是相对于包含面板选择放置 Polyline 的位置的。
Polygon 拆线(封闭图形)
Polygon与Polyline非常相似。它有一个Points属性,其工作方式与Polyline 的完全相同。唯一的区别是Polyline总是绘制一个开放的形状,而Polygon总是绘制一个闭合的形状
<Polyline Fill="Orange" Stroke="Blue" StrokeThickness="2" Points="40,10 70,50 10,50" /> <Polygon Fill="Orange" Stroke="Blue" StrokeThickness="2" Points="40,10 70,50 10,50" />
Path 路径
路径是迄今为止最强大的形状。为方便起见,我们目前看到的所有形状都已提供,因为可以使用路径绘制所有形状。 Path还可以绘制比我们之前看到的形状更复杂的形状。
Bitmaps 位图
WPF 支持以下任何格式的位图:
* BMP、JPEG、PNG、TIFF、Windows Media Photo、GIF 和 ICO(Windows 图标文件)。您可以使用任何图像格式创建画笔来绘制任何形状或文本,如本章后面
“ImageBrush”部分所述。 System.Windows.Media.Imaging命名空间提供的类可让您处理图像文件的像素和元数据。但是,使用位图的最简单方法是使用Image元素。
<Image Source="http://www.interact-sw.co.uk/images/M3/BackOfM3.jpeg" />
将Source属性设置为绝对 URL 会导致下载并显示图像
<Image Source="/Images/Face.jpg" />
将图像文件作为资源嵌入到您的应用程序中
Image元素能够调整图像的大小。确切的行为取决于您的应用程序的布局。如果您的布局允许Image元素根据内容调整大小,它将以其自然大小显示图像。
Canvas面板从不为其子面板强加特定尺寸,因此例 13‑29 中的代码将以原始尺寸显示图像。
<Canvas> <Image Source="/Images/Face.jpg" /> </Canvas>
但是,如果您的布局为Image元素提供了特定的空间量,则默认情况下将缩放位图以填充该空间