形状,画刷和变换
   概述:

在许多用户界面技术中,普通控件和自定义绘图之间具有清晰的区别。通常来说,绘图特性只用于特定的应用程序--如游戏,数据可视化和物理仿真等。而WPF具有一个非常不同的原则。它以相同的方式处理控件和绘制的图形。
 一.理解形状。
       在WPF用户界面中,绘制2D图形内容的最简单方法是使用形状(shape) :专门用于表示简单的直线,椭圆,矩形以及多边形的类。从技术角度讲,形状就是所谓的绘图图元。可以组合这些基本元素来创建更复杂的图形。形状最重要的细节是,它们都继承自FrameworkElement类。因此,形状是元素。这样会带来许多重要的结果:
     1.形状绘制自身。不需要管理无效的情况和绘图过程。如:当移动内容,改变窗口尺寸或改变形状属性时,不需要手动重新绘制形状。
    2.使用与其他元素相同的方式组织形状。换句话说,可在学过的任何布局容器中放置一个形状(尽管,Canvas明显是最有用的容器,因为它允许在特定的坐标位置放置形状,当构建复杂的具有多个部分的图画时,这是很重要的)。
     3.形状支持与其他元素相同的事件。这意味着为了处理焦点,按下键盘,移动鼠标以及单击鼠标等,不需要进行任何额外的工作。可以使用用于其他元素的相同的事件集,并且同样支持工具提示,上下文菜单和拖放操作。

二.Shape 类
     每个形状都继承自抽象的System.Windows.Shapes.Shape类。如下显示了形状类的继承层次。

如图 ,只有很少一部分类继承自Shape类。Line(直线),ellipse(椭圆),Rectangle(长方形,矩形),Polyline是一系列相互连接的直线,Polygon是由一系列相互连接的直线形成的闭合图形,最后Path类具有非常强大的功能,能够将多个基本形状组合成一个单独的元素。

<Window xmlns:my="clr-namespace:StudyWPF"  x:Class="StudyWPF.形状画刷"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="形状画刷" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0">
            <Line Stroke="Blue" X1="0" Y1="0" X2="300" Y2="50"></Line>
        </StackPanel>
        <Canvas Grid.Row="1">
            <Ellipse Fill="Tomato" Stroke="Blue" Height="50" Width="100" Margin="5" HorizontalAlignment="Left"></Ellipse>
            <Rectangle Fill="Bisque"  Stroke="Red" Height="50" RadiusX="20" RadiusY="20" Width="100" Margin="5" HorizontalAlignment="Left"></Rectangle>
            <Ellipse Fill="RoyalBlue" Stroke="Blue" Canvas.Left="100" Canvas.Top="50" Width="100" Height="50"></Ellipse>
            <Rectangle Fill="DeepSkyBlue" Stroke="Blue" Canvas.Left="30" Canvas.Top="40" Width="100" Height="50"></Rectangle>
           
        </Canvas>
    </Grid>
</Window>
Ellipse类没有增加任何属性。Rectangle类只增加了两个属性:RadiusX和RadiusY。如果将这两个属性的值设置成非零,就可以创建出优美的圆形拐角

三。形状的布局:

1.  形状位置 设置:通常不希望使用StackPanel,DockPanle以及WrapPanel面板,因为它们被设计为独立的元素,Grid面板更灵活一些,因为它允许在同一个单元格中放置任意多个元素(尽管不能在单元格中的不同部分定位矩形和椭圆)所以最理想的容器是Canvas,该容器要求使用Left,Top,Right或Bottom附加属性,为每个形状指定坐标。这样可以完全控制形状如何相互重叠;如果使用Canvas容器,标签的顺序是很重要的,在上面的示例中,矩形叠加在椭圆的上面,因为在标签列表中首先出现的是椭圆,所以首先绘制椭圆。
  并且:Canvas 容器不需要占据整个窗口。例如,完全可以创建一个Grid面板,并在Grid面板的一个单元格中使用Canvas容器。对于在一个动态的,可以自由流动的用户界面中锁定一小部分绘图逻辑,这是一种非常好的方法。

2.使用viewBox控件缩放形状:
        使用Canvas控件的唯一限制是图形不能改变自身的尺寸以适应更大或更小的窗口。对于按键这非常合理(在这些情况下,按钮不改变尺寸),但是对于其他类型的图形内容,情况就不同了。例如,可能创建一个希望可以改变大小的复杂图形,从而可以充分利用可用的空间。如果希望联合Canvas控件的精确控制功能和容易改变尺寸功能,可以使用Viewbox元素。用法如下: <Viewbox  HorizontalAlignment="Center" Width="45" Height="45" Grid.Row="3" Name="lblProgress" Grid.Column="2" Visibility="Collapsed">
                <Canvas RenderTransformOrigin="0.5,0.5"
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Width="120" Height="120" >
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="20.1696"
                         Canvas.Top="9.76358"
                         Stretch="Fill" Fill="Orange"
                         Opacity="1.0"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="2.86816"
                         Canvas.Top="29.9581" Stretch="Fill"
                         Fill="Black" Opacity="0.9"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="5.03758e-006"
                         Canvas.Top="57.9341" Stretch="Fill"
                         Fill="Black" Opacity="0.8"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="12.1203"
                         Canvas.Top="83.3163" Stretch="Fill"
                         Fill="Black" Opacity="0.7"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="36.5459"
                         Canvas.Top="98.138" Stretch="Fill"
                         Fill="Black" Opacity="0.6"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="64.6723"
                         Canvas.Top="96.8411" Stretch="Fill"
                         Fill="Black" Opacity="0.5"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="87.6176"
                         Canvas.Top="81.2783" Stretch="Fill"
                         Fill="Black" Opacity="0.4"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="98.165"
                         Canvas.Top="54.414" Stretch="Fill"
                         Fill="Black" Opacity="0.3"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="92.9838"
                         Canvas.Top="26.9938" Stretch="Fill"
                         Fill="Black" Opacity="0.2"/>
                    <Ellipse Width="21.835" Height="21.862"
                         Canvas.Left="47.2783"
                         Canvas.Top="0.5" Stretch="Fill"
                         Fill="Black" Opacity="0.1"/>
                    <Canvas.RenderTransform>
                        <RotateTransform x:Name="SpinnerRotate"
                                     Angle="0" />
                    </Canvas.RenderTransform>
                    <Canvas.Triggers>
                        <EventTrigger RoutedEvent="ContentControl.Loaded">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation
                                    Storyboard.TargetName
                                        ="SpinnerRotate"
                                     Storyboard.TargetProperty
                                        ="(RotateTransform.Angle)"
                                     From="0" To="360"
                                     Duration="0:0:01"
                                     RepeatBehavior="Forever" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </Canvas.Triggers>

</Canvas>
            </Viewbox>

3 。 直线:Line形状表示连接一个点和另一个点的一条直线。起点和终点由4个属性设置:(X1,Y1) (X2,Y2)
对于直线,Fill属性不起作用,必须设置Stroke属性。在直线中使用的坐标是相对于放置直线的矩形的左上角的坐标(添加直线时会在容器中保留一块矩形空间用于放置直线,)

4 . 拆线:通过Polyline类可以绘制一系列相互连接的直线。只需要使用Points属性提供一系列X和Y坐标。从技术角度讲,Points属性需要一个PointCollection对象,但是在XAML中使用基于简单字符串的语法
<Polyline Stroke="Blue" StrokeThickness="5" Points="10,150 30,140 50,160 70,130 90,170 110,120 130,180 150,110 170,190 190,100 210,240"></Polyline>

WPF学习系列之八(形状,画刷和变换)的更多相关文章

  1. WPF 10天修炼 第八天 - 形状、画刷和变换

    图形 在WPF中使用绘图最简单的就是使用Shape类.Shape类继承自FrameworkElement,是一个专门用来绘图的类.Shape类中年派生的类有直线.矩形.多边形和圆形等. System. ...

  2. WPF学习系列 游戏-选张图片做成9宫格拼图

    今天要学习一个拼图项目. 目标是传入一张图片,然后将它分成9份,去掉一份,鼠标点击进行拼图. 源文件结构很简单 第一步.新建项目 这一步没什么好说的,新建一个项目就跟源文件结构一样了 第二步.页面布局 ...

  3. WPF学习系列之七 (样式与行为)

    样式(Styles)是组织和重用格式化选项的重要工具.不是使用重复的标记填充XAML,以设置诸如边距.颜色及字体等细节,而可以创建一系列封装所有这些细节的样式.然后可以在需要之处通过一个属性应用样式. ...

  4. Dubbo学习系列之八(分布式事务之MQ方案)

    自从小王玩起了微服务,发现微服务果然很强大,好处真是太多,心中暗喜,然而,却也遇到了分布式中最棘手的问题:分布式事务.小王遍访各路神仙,也无个完美开源解决方案,当然,也有些实际可行的手法,虽不算完美, ...

  5. WPF学习系列之五(WPF控件)

    控件:    1.内容控件------这些控件能够包含嵌套的元素,为它们提供几乎无限的显示能力.内容控件包括Lable,Button 以及ToolTip类. 内容控件是更特殊的控件类型,它们可以包含( ...

  6. WPF学习系列 简单的窗体设置

    今天要学习的源码是一个窗体设置.效果如下,可拖拽.这让我想起了vs的启动界面 下面是源码的情况 项目结构: 窗体代码: cs代码 1.新建项目 略 2.设置窗体 AllowsTransparency= ...

  7. WPF学习系列 绘制旋转的立方体

    我是一年经验的web程序员,想学习一下wpf,比较喜欢做项目来学习,所以在网上找了一些项目,分析代码,尽量能够做到自己重新敲出来 第一个项目是 中间的方块会不停的旋转. 第一步,新建wpf项目 第二步 ...

  8. Gradle学习系列之八——构建多个Project

    在本系列的上篇文章中,我们讲到了Gradle的依赖管理,在本篇文章中,我们将讲到如何构建多个Project. 请通过以下方式下载本系列文章的Github示例代码: git clone https:// ...

  9. WPF学习系列之六 (元素绑定)

    元素绑定 简单地说,数据绑定是一种关系,该关系告诉WPF从一个源对象提取一些信息,并使用这些信息设置目标对象的属性.目标属性总是依赖属性,并且通常位于WPF元素中. 一.将元素绑定到一起 <Wi ...

随机推荐

  1. eclipse常用插件安装

    打开资源文件所在目录 EasyExplorer 下载:http://sourceforge.net/projects/easystruts/ 直接拷贝到%ECLIPSE_HOME%\plugins 或 ...

  2. linux命令(12)uniq去重

    转载地址:http://blog.51yip.com/shell/1022.html 实例详细说明linux下去除重复行命令uniq 一,uniq干什么用的 文本中的重复行,基本上不是我们所要的,所以 ...

  3. 转-Activity之间数据传递之Intent数据传递

    Intent意图 可用于Activity之间的数据传递,一般可分为下面两种情况,从当前Activity传递到目标Activity后有无返回值: 1.传递后无返回值的情况: 1 2 3 4 5 6 7 ...

  4. 通过JSTL+EL实现循环迭代

    使用前需要导入包 jstl.jar 和 standard.jar <%@ page language="java" import="java.util.*,com. ...

  5. git重写历史记录

    1 修改上一次历史提交,替换掉上次的提交git commit --amend 2 git rebase 将不同分支路径合并到同一分支路径上eg:将master分支上的 conflic rebase合并 ...

  6. [ActionScript 3.0] AS3.0根据当天日期获取明天,后天...日期

    const dayTime:Number=24*3600*1000//一天毫秒数 var date:Date = new Date(); trace("今天:"+ date.toD ...

  7. JAVA中压缩与解压缩

    以压缩Zip文件为例.主要是通过ZipOutputStream类实现.解压缩主要使用ZipFile类和ZipInputStream以及ZipEntry类. package main; import j ...

  8. Oracle 的简单描述

    在 Oracle 开发中,客户端把 SQL 语句发送给服务器,服务器对 SQL 语句进行编译.执行,把执行的结果返回给客户端. Oracle SQL 语句由如下命令组成:  数据定义语言( DDL) ...

  9. LeetCode 58. Length of Last Word

    Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...

  10. 源码解读—Stack

    Stack特性:先进后出.后进先出 java.util.Stack实现了这一数据结构. public  class Stack<E> extends Vector<E>,Sta ...