在许多用户界面技术中,普通控件和自定义绘图之间具有清晰的区别。通常来说,绘图特性只用于特定的应用程序。例如,游戏、数据可视化和物理仿真等。WPF具有一个非常不同的原则。它以相同的方式处理预先构建的控件和自定义绘制的图形。不仅可以使用WPF的绘图支持为用户界面创建付图形的可视化元素,还可以通过他最大限度的利用动画和控件模板等特性。本次分析WPF的2D绘图特性,首先是用于形状回执的基本元素。接着将分析如何使用画刷绘制替他们的边框和内部。然后学习如何使用变换对形状和元素进行旋转、扭曲以及其他操作。最后学习使形状和其他元素半透明。

12.1 理解形状

  在WPF用户界面中,绘制2D图形内容的最简单方法是使用形状(shape):专门用于表示简单的直线、椭圆、矩形以及多边形的类。从技术角度来看,形状就是所谓的绘图图元(primitive)。WPF中形状的最重要的细节是,它们都继承自FrameworkElement类。因此,形状是元素。这样的结果是:

  • 形状绘制自身。不需要管理无效的情况和绘图过程。例如,当移动内容、改变窗口尺寸或改变形状属性时,不需要手动重新绘制形状。
  • 使用与其他元素相同的方式组织形状。也就是可以在任何布局容器中放置一个形状。
  • 形状支持与其他元素相同的事件。这意味着为了处理焦点、按下键盘、移动鼠标以及单击鼠标等,不需要进行任何额外的工作。可以使用用于其他元素的相同的事件集,并且同样支持工具提示、上下文菜单和拖放操作。

12.1.1 Shape类

  呢个形状都继承自抽象的System.Windows.Shapes.Shape类。如下图显示了形状类的继承层次。WPF形状、画刷和变换

只有很少一部分继承自Shape类。Line、Ellipse以及Rectangle都很直观,Polyline是一系列相互连接的直线Polygon是由一系列相互连接的直线形成的闭合图形。最后,Path类具有非常强大的功能,能够将多个基本形状组合成一个单独的元素。尽管Shape类自身不能执行任何工作,但是它定义了少量的重要属性,如下列表

File  设置绘制形状表面(边框内的所有内容)的画刷对象
Stroke 设置绘制形状边缘(边框)的画刷对象 
StrokeThickness 使用设备无关单位,设置边框的宽度。 

StrokeStartLineCap

和StrokeEndLineCap

 决定直线开始端和结束端边缘的轮廓。这些属性只影响Line、Polyline以及Path形状。所有其他形状是闭合的,没开始点和结束点

StrokeDashArray、

StrokeDashOffset

和StrokeDashCap

用于在形状周围创建点划线边框。可以控制点划线的尺寸和频率,以及每条点划线开始端和结束端边缘的轮廓 
StrokeLineJoin和SrokeMiterLimit 确定形状拐角处的轮廓。对于没有拐角的形状,如Line和Ellipse,这些熟悉不起作用 
Stretch 确定形状如何填充可用的区域。可以使用该属性创建能够扩展以适合其容器的形状。还可以为HorizontalAlignment或VerticalAlignmet属性(这些属性继承自FramenworkElement类)使用一个Streth值强制形状在一个方向上扩展 
DefiningGeometry 为形状提供一个Geometry对象。Geometry对象描述了形状的坐标和尺寸,不包括UIElement类的相关内容,例如对键盘和鼠标事件的支持。 
GeometryTransform 通过该属性可以应用一个Transform对象,改变用于绘制形状的坐标系统。从而可以扭曲、旋转或移动性状。 
RenderedGeometry 提供描述最终的、以渲染好的图形的Geometry对象。 

12.1.2 矩形和椭圆

  矩形和椭圆是最简单的形状。为了创建矩形或椭圆,需要设置熟悉的Height和Width属性来定义形状的尺寸,然后设置Fill或Stroke属性使形状可见。如下放置了一个椭圆和一个矩形

    <StackPanel>
      <Ellipse Fill="Yellow" Stroke="Blue" 
               Width="100" Height="50" Margin="5" HorizontalAlignment="Left"></Ellipse>
      <Rectangle Fill="Yellow" Stroke="Blue" 
                 Width="100" Height="50" Margin="5"  HorizontalAlignment="Left"></Rectangle>
    </StackPanel>

Ellipse类没有增加任何属性。Rectangle类只增加了两个属性:RadiusX和RadiusY。如果将这两个属性的值设置为非零值,就可以创建出优美的圆形拐角。随着它们的值的增大矩形拐角部分会更多的被替换。如果一个值大于另一个值的话,值较大的一个方向的拐角会更加平缓,而另一个方向的拐角会更尖锐。如果它们的值分别等于矩形的宽和高时,矩形就会变成椭圆。

12.1.3 改变形状的尺寸和放置形状

  硬编码尺寸通常不是创建用户界面的理想方法。它们会限制处理动态内容的能力,并且会使应用程序本地化到去他语言变得更加困难。通常,需要更加严格地控制形状的位置。Ellipse和Rectangle为了适应可用的空间,都能够自动改变它们自身。如果没有提供Height和Width属性,形状会根据他们的容器来设置自身的尺寸。改变形状尺寸的行为依赖于Strech属性的值(该属性是在Shape类中定义的)。默认情况下该属性的值为File。下表中是Stretch属性的所有值。

File 形状拉伸其宽度和高度以及确切的适应其容器(如果设置了明确的高度和宽度此设置失效)
None 形状不被拉伸。除非使用Height和Width属性(或者使用MinHeight和MinWidth)将形状的宽度和高度设置为非0的值,否则不会显示形状
Uniform 按比例改变形状的宽度和高度,直到形状到达容器边缘。
UniformToFill 按比例改变形状的高度和宽度,直到形状填满了整个可用空间的高度和宽度。

如下示例,显示了上面三种枚举值的区别

    <Ellipse Fill="Yellow" Stroke="Blue" Stretch="Fill"></Ellipse>
    <Ellipse Fill="Yellow" Stroke="Blue" Grid.Column="1" Stretch="Uniform"></Ellipse>
    <Ellipse Fill="Yellow" Stroke="Blue" Grid.Column="2" Stretch="UniformToFill "></Ellipse>

WPF形状使用于其他元素相同的布局系统。然而,有些局部容器是不合适的。如StackPanel、DockPanle以及WrapPanel面板,因为它们被设计为独立的元素。Grid面板更加灵活,因为它允许在同一单元格中放置任意多个元素。理想的容器是Canvas,该容器可以完全控制性状如何相互重叠:

    <Canvas Grid.Row="1">
      <Ellipse Fill="Yellow" Stroke="Blue" Canvas.Left="100"  Canvas.Top="50"
               Width="100" Height="50" ></Ellipse>
      <Rectangle Fill="Yellow" Stroke="Blue" Canvas.Left="30"  Canvas.Top="40"                 
                 Width="100" Height="50" ></Rectangle>
    </Canvas>

12.1.4 使用ViewBox控件缩放形状

  使用Canvas控件的唯一限制是图形不能改变自身的尺寸以适应更大或更小的窗口。WPF提供了比较容易的解决方法。如果希望联合Canvas控件的精确控制功能和容易的改变尺寸的功能,可以使用Viewbox元素。Viewbox是一个继承自Decorator的简单类。该类只接受一个子元素,并且拉伸或缩小其子元素以适应可用的空间。Viewbox经常用于矢量图形。如下示例

  <Grid Margin="5">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"></RowDefinition>
      <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>

    <TextBlock>The first row of a grid.</TextBlock>

    
    <Viewbox Grid.Row="1" HorizontalAlignment="Left"  MaxHeight="500">

      <Canvas Width="200" Height="150">
        <Ellipse Fill="Yellow" Stroke="Blue" Canvas.Left="10"  Canvas.Top="50"
               Width="100" Height="50" HorizontalAlignment="Left"></Ellipse>
      <Rectangle Fill="Yellow" Stroke="Blue" Canvas.Left="30"  Canvas.Top="40"                 
                 Width="100" Height="50" HorizontalAlignment="Left"></Rectangle>
    </Canvas>
    </Viewbox>
  </Grid>
View Code

相关文章:

  • 2022-12-23
  • 2021-08-08
  • 2021-12-30
  • 2023-03-20
  • 2021-12-27
  • 2021-08-18
  • 2021-10-31
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-05-18
相关资源
相似解决方案