形状,画刷和变换
   概述:

在许多用户界面技术中,普通控件和自定义绘图之间具有清晰的区别。通常来说,绘图特性只用于特定的应用程序--如游戏,数据可视化和物理仿真等。而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. Android sqlite管理数据库基本用法

    Android操作系统中内置了sqlite数据库(有关sqlite数据库详细介绍见:http://zh.wikipedia.org/wiki/SQLite),而sqllite本身是一个很小型的数据库, ...

  2. HelloHibernate详解

    1. Configuration管理读取配置文件 //读取src下hibernate.properties,不推荐使用 Configuration cfg = new Configuration(); ...

  3. iis7 500错误日志报 LOG_FILE_MAX_SIZE_TRUNCATE

    参考:http://blogs.iis.net/robert_mcmurray/freb-log-file-max-size-truncate cd /d "%windir%\system3 ...

  4. nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)

    启动nginx时报这个错 , 要么用root用户启动 , 要么在配置文件nginx.conf中将server下的listen端口改掉 , 因为在linux中端口号小于1024都是需要root权限的

  5. heredoc和nowdoc的区别

    heredoc使用 <<< EOT 的标示符,而nowdoc使用 <<< 'EOT' 这样的标示符,其中nowdoc是PHP5.3引进的新技术,它包含了heredo ...

  6. UML系列图--用例图

    UML-Unified Model Language 统一建模语言,又称标准建模语言.是用来对软件密集系统进行可视化建模的一种语言. 在UML系统开发中有三个主要的模型: 功能模型: 从用户的角度展示 ...

  7. Java多线程之阻塞I/O如何中断

    阻塞的I/O线程在关闭线程时并不会被打断,需要关闭资源才能打断. 1.执行socketInput.close();阻塞可中断.2.执行System.in.close();阻塞没有中断. package ...

  8. android之location 根据接口获取经纬度信息

    http://maps.googleapis.com/maps/api/geocode/json?address=%E7%A6%8F%E5%BB%BA&sensor=falsehttp://m ...

  9. DataTable中的数据赋值给model z

    create table memberinfo ( member_id int, member_name varchar(20), member_birthday varchar(50) ) go / ...

  10. linux 交换分区分配规则

    一般地, 内存小于2G ,则swap=2*RAM, 内存大于2G, 则swap=2+RAM, 然后满足上述规则就行.