形状,画刷和变换
   概述:

在许多用户界面技术中,普通控件和自定义绘图之间具有清晰的区别。通常来说,绘图特性只用于特定的应用程序--如游戏,数据可视化和物理仿真等。而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. 【转】c# winform DataGridView导出数据到Excel中,可以导出当前页和全部数据

    准备工作就是可以分页的DataGridView,和两个按钮,一个用来导出当前页数据到Excel,一个用来导出全部数据到Excel 没有使用SaveFileDialog,但却可以弹出保存对话框来 先做导 ...

  2. extern 修饰符

    extern(C# 参考) extern 修饰符用于声明在外部实现的方法. extern 修饰符的常见用法是在使用 Interop 服务调入非托管代码时与 DllImport 特性一起使用.在这种情况 ...

  3. working copy locked 问题

    解法 1 :  右键svn-->clean up 解法 2 :  被lock的文件夹进入控制台 del lock /q/s [转载解法] SVN 本地更新时,由于一些操作中断更新,如磁盘空间不够 ...

  4. 网页爬虫--scrapy入门

    本篇从实际出发,展示如何用网页爬虫.并介绍一个流行的爬虫框架~ 1. 网页爬虫的过程 所谓网页爬虫,就是模拟浏览器的行为访问网站,从而获得网页信息的程序.正因为是程序,所以获得网页的速度可以轻易超过单 ...

  5. (转)HelloWorld CMake CMake中构建静态库与动态库及其使用

    继续完善Hello World,建立它的共享库, 包括静态库和动态库. 本节的任务: 1,建立一个静态库和动态库,提供HelloFunc函数供其他程序编程使用,HelloFunc 向终端输出Hello ...

  6. 安装Android SDK和ADT步骤和遇到的问题

    http://894503895.diandian.com/post/2012-05-16/18695648 1.安装eclipse.下载地址:http://www.eclipse.org/downl ...

  7. 关于Switch结构利用

    三大流程结构,循环.分支.if ,循环与条件选择结构用的比较多,而swicth用的比较少,swicth可以用if代替,只不过麻烦,最终都能实现输入和输出的条件对应     Swicth利用       ...

  8. 设置oracle_home

    set ORACLE_HOME=F:\app\rh\product\11.2.0\dbhome_1

  9. [Java] 01 String 内存分析

    public class StringTest{ public static void main(String[] args){ String str1 = new String("123& ...

  10. JAVA中复写equals方法

    在JAVA中“==”用于比较两个引用对象的地址是否相同.但是如果我们想比较两个对象的内容是否相同,通常会覆写equals方法.equals方法用来比较两个对象的内容是否相等. package org. ...