首页 > 其他分享 >13.画刷(Brush)

13.画刷(Brush)

时间:2024-02-01 15:22:24浏览次数:26  
标签:13 set 画刷 DependencyProperty get 渐变 static Brush public

在进行WPF界面设计时,我们需要在很多地方设置颜色属性,比如元素的背景色、前景色以及边框的颜色,还有形状的内部填充和笔画,这些颜色的设置在WPF中都以画刷(Brush)的形式实现。比如最常用的画刷就是SolidColorBrush,它表示一种纯色。

public abstract class Brush : Animatable, IFormattable, IResource
{
    public static readonly DependencyProperty OpacityProperty;
    public static readonly DependencyProperty TransformProperty;
    public static readonly DependencyProperty RelativeTransformProperty;
 
    protected Brush();
 
    public double Opacity { get; set; }
    public Transform Transform { get; set; }
    public Transform RelativeTransform { get; set; }
 
    public Brush Clone();
    public Brush CloneCurrentValue();
    public override string ToString();
    public string ToString(IFormatProvider provider);
 
}

Brush继承于Animatable基类和Freezable基类,说明它支持更改通知。如果改变了画刷,任何使用该画刷的控件的颜色都会自动重绘。

Opacity 属性表示它支持部分透明。

Brush一共有7个子类,下表中列出了它们的信息。

画刷名称 功能说明
SolidColorBrush 使用单一的连续颜色填充区域
LinearGradientBrush 使用线性渐变绘制区域。
RadialGradientBrush 使用径向渐变绘制区域。 焦点定义渐变的开始,而圆定义渐变的终点。
ImageBrush 使用图像绘制区域。
VisualBrush 使用一个视图绘制区域。
BitmapCacheBrush 绘制带有缓存的内容的区域。
DrawingBrush 使用包括形状、文本、视频、图像或其他绘制项等填充区域。

Brush基类和子类的继承关系

 

SolidColorBrush纯色画刷

SolidColorBrush继承于Brush抽象类,表示用某一种颜色填充区域。从定义上看,它拥有一个Color属性,表示具体的颜色值。

public sealed class SolidColorBrush : Brush
{
    public static readonly DependencyProperty ColorProperty;
 
    public SolidColorBrush();
    public SolidColorBrush(Color color);
 
    public Color Color { get; set; }
 
    public static object DeserializeFrom(BinaryReader reader);
    public SolidColorBrush Clone();
    public SolidColorBrush CloneCurrentValue();
}

Color 在WPF中代表颜色值,被设计成一个结构体,主要是4个属性,即A、R、G、B,分别表示Alpha透明通道值,红色通道值、绿色通道值和蓝色通道值。它们的取值范围都是0-255

案列:

设置Grid的背景颜色

<Grid>
    <Grid.Background>
        <SolidColorBrush>
            <SolidColorBrush.Color>
                <Color A="255" R="255" G="0" B="0"/>
            </SolidColorBrush.Color>
        </SolidColorBrush>
    </Grid.Background>
</Grid>

C#代码的方式去设置背景颜色

SolidColorBrush solidColorBrush = new SolidColorBrush();
//使用系统自定义的颜色
solidColorBrush.Color = Colors.Green;
//或者从Color的FromRgb成员中得到颜色
solidColorBrush.Color = Color.FromRgb(0, 0x80, 0);
grid.Background = solidColorBrush;

实例化成一个资源:

<Window.Resources>
    <SolidColorBrush x:Key="BackgroundBrush" Color="#123456"/>
</Window.Resources>
<Grid x:Name="grid" Background="{StaticResource BackgroundBrush}"/>

 

LinearGradientBrush渐变画刷

LinearGradientBrush是一个比较有意思的画刷,它可以从一种颜色过渡到另一种颜色,使被填充的区域呈现渐变效果

public sealed class LinearGradientBrush : GradientBrush
{
    public static readonly DependencyProperty StartPointProperty;
    public static readonly DependencyProperty EndPointProperty;
 
    public LinearGradientBrush();
    public LinearGradientBrush(GradientStopCollection gradientStopCollection);
    public LinearGradientBrush(GradientStopCollection gradientStopCollection, double angle);
    public LinearGradientBrush(Color startColor, Color endColor, double angle);
    public LinearGradientBrush(GradientStopCollection gradientStopCollection, Point startPoint, Point endPoint);
    public LinearGradientBrush(Color startColor, Color endColor, Point startPoint, Point endPoint);
 
    public Point StartPoint { get; set; }
    public Point EndPoint { get; set; }
 
    public LinearGradientBrush Clone();
    public LinearGradientBrush CloneCurrentValue();
}

从定义上看,它有StartPoint 和EndPoint 两个点,表示获取和设置线性渐变的二维起始坐标和结束坐标。而它因为继承于GradientBrush基类,所以它的颜色都保存在GradientStops集合属性中。GradientStops集合中的元素类型必须为GradientStop,表示渐变中转换点的位置和颜色。所以,GradientStop拥有Color属性和Offset属性,分别表示颜色值和偏移值。

案例:

一个Grid,希望从左上角设置一个绿色,右下角设置一个蓝色,中间是两种颜色的渐变效果

<Grid>
    <Grid.Background>
        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
            <GradientStop Color="Green" Offset="0"/>
            <GradientStop Color="Blue" Offset="1"/>
        </LinearGradientBrush>
    </Grid.Background>        
</Grid>

LinearGradientBrush将整个Grid看成是一个0-1的矩形,所以StartPoint=(0,0)表示左上角,EndPoint=(1,1)表示右下角,这就控制了渐变的方向是从左上角到右下角的斜线。GradientStop 对象中的Offset表示在渐变方向上各颜色的占比或起点。假如我们将第一个GradientStop对象的Offset设置为0.5,那么此时的代码和效果如下所示:

<Grid>
    <Grid.Background>
        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
            <GradientStop Color="Green" Offset="0.5"/>
            <GradientStop Color="Blue" Offset="1"/>
        </LinearGradientBrush>
    </Grid.Background>        
</Grid>

 

RadialGradientBrush径向渐变

RadialGradientBrush径向渐变像一个圆一样,从焦点中心位置开始向四周渐变,LinearGradientBrush线性渐变具有用于定义渐变矢量的起点和终点,而径向渐变具有一个圆和一个焦点,用于定义渐变行为。 圆定义渐变的终点。 换句话说,渐变停止点为 1.0 定义圆周的颜色。 焦点定义渐变的中心。 渐变停止点为 0.0 定义焦点处的颜色。

public sealed class RadialGradientBrush : GradientBrush
{
    public static readonly DependencyProperty CenterProperty;
    public static readonly DependencyProperty RadiusXProperty;
    public static readonly DependencyProperty RadiusYProperty;
    public static readonly DependencyProperty GradientOriginProperty;
 
    public RadialGradientBrush();
    public RadialGradientBrush(GradientStopCollection gradientStopCollection);
    public RadialGradientBrush(Color startColor, Color endColor);
 
    public Point Center { get; set; }
    public double RadiusX { get; set; }
    public double RadiusY { get; set; }
    public Point GradientOrigin { get; set; }
 
    public RadialGradientBrush Clone();
    public RadialGradientBrush CloneCurrentValue();
}

Center属性:获取或设置径向渐变的最外面圆的中心。

RadiusX属性:获取或设置径向渐变的最外面圆的水平半径。默认值为 0.5。

RadiusY属性:获取或设置径向渐变的最外面圆的垂直半径。默认值为 0.5。

GradientOrigin属性:获取或设置用于定义渐变开始的二维焦点的位置。默认值为 0.5。

以Ellipse控件为例,演示一下RadialGradientBrush 的用法:

<Grid x:Name="grid">
    <Ellipse Width="200" Height="200">
        <Ellipse.Fill>
            <RadialGradientBrush GradientOrigin="0.5,0.5" 
                                 RadiusX="0.75" 
                                 RadiusY="0.75">
                <RadialGradientBrush.GradientStops>
                    <GradientStop Color="White" Offset="0" />
                    <GradientStop Color="Black" Offset="0.65" />
                    <GradientStop Color="Gray" Offset="0.8" />
                </RadialGradientBrush.GradientStops>
            </RadialGradientBrush>
        </Ellipse.Fill>
    </Ellipse>
</Grid>

在上面的代码中,处于圆中心的白色渐变点由GradientOrigin属性控制,如果将值改成:GradientOrigin="0.25,0.25",那么它会呈现下面的样子。

根据这个特性,我们可以实现一个有趣的示例。那就是当鼠标移动到椭圆内,这个径向渐变的起点坐标跟随鼠标位置变化而变化。

 <Grid x:Name="grid">
        <Ellipse x:Name="ellipse" 
                 Width="200" 
                 Height="200" 
                 MouseMove="ellipse_MouseMove">
            <Ellipse.Fill>
                <RadialGradientBrush GradientOrigin="0.25,0.25" 
                                     RadiusX="0.75" 
                                     RadiusY="0.75">
                    <RadialGradientBrush.GradientStops>
                        <GradientStop Color="White" Offset="0" />
                        <GradientStop Color="Goldenrod" Offset="0.65" />
                        <GradientStop Color="Gray" Offset="0.8" />
                    </RadialGradientBrush.GradientStops>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>            
    </Grid>
private void ellipse_MouseMove(object sender, MouseEventArgs e)
{
    Ellipse ellipse = e.Source as Ellipse;
    Point point = e.GetPosition(ellipse);
    double width = ellipse.Width;
    double height = ellipse.Height;
    RadialGradientBrush brush = ellipse.Fill as RadialGradientBrush;
    double x = point.X / width;
    double y = point.Y / height;
    brush.GradientOrigin = new Point(x, y);
}

 

ImageBrush图像画刷

ImageBrush表示使用图像绘制区域。它继承于TileBrush抽象基类,另外,DrawingBrush和VisualBrush也继承于TileBrush抽象基类。

TileBrush 有三种不同类型,其中每一种都使用不同类型的内容进行绘制。下面列出它3个子类的情况。

  • 若使用ImageBrush子类,则画刷的填充内容是图像;
  • 若使用DrawingBrush子类,则画刷的填充内容是绘图;
  • 若使用VisualBrush子类,则画刷的填充内容是视觉对象(视觉树或控件);
public abstract class TileBrush : Brush
{
    public static readonly DependencyProperty ViewportUnitsProperty;
    public static readonly DependencyProperty ViewboxUnitsProperty;
    public static readonly DependencyProperty ViewportProperty;
    public static readonly DependencyProperty ViewboxProperty;
    public static readonly DependencyProperty StretchProperty;
    public static readonly DependencyProperty TileModeProperty;
    public static readonly DependencyProperty AlignmentXProperty;
    public static readonly DependencyProperty AlignmentYProperty;
 
    protected TileBrush();
 
    public TileMode TileMode { get; set; }
    public Stretch Stretch { get; set; }
    public Rect Viewbox { get; set; }
    public Rect Viewport { get; set; }
    public AlignmentY AlignmentY { get; set; }
    public BrushMappingMode ViewportUnits { get; set; }
    public AlignmentX AlignmentX { get; set; }
    public BrushMappingMode ViewboxUnits { get; set; }
 
    public TileBrush Clone();
    public TileBrush CloneCurrentValue();
    protected abstract void GetContentBounds(out Rect contentBounds);
}

TileMode 属性:获取或设置基本图块如何填充区域。枚举型,它一共有5个值,Tile表示在可用区域复制图像;FlipX表示复制图像但垂直翻转每个第二列;FlipY表示复制图像但水平翻转每个第二行;FlipXY表示复制图像,但是垂直翻转每个第二列,半水平翻转每个第二行。
Stretch 属性:获取或设置内容如何拉伸。
Viewbox 属性:获取或设置图块中内容的位置和尺寸。
Viewport 属性:获取或设置基本图块的位置和尺寸。它的类型是Rect,也就是用它来指定截取原图片的某个区域进行填充,这个区域的设置可以用绝对值和相对值两种方式设置,对应属性是ViewboxUnits,它有两个值,Absolute表示取绝对坐标,RelativeToBoundingBox表示取相对坐标。
AlignmentY属性:获取或设置基本图块的垂直对齐方式。
AlignmentX属性:获取或设置基本图块的垂直水平方式。
ViewboxUnits属性:获取或设置Viewbox的值是相对内容的边界框而言,还是绝对值。
ViewportUnits属性:获取或设置Viewport的值 是否是相对于输出区域的大小。

ImageBrush的定义:

public sealed class ImageBrush : TileBrush
{
    public static readonly DependencyProperty ImageSourceProperty;
 
    public ImageBrush();
    public ImageBrush(ImageSource image);
 
    public ImageSource ImageSource { get; set; }
 
    public ImageBrush Clone();
    public ImageBrush CloneCurrentValue();
    protected override Freezable CreateInstanceCore();
    protected override void GetContentBounds(out Rect contentBounds);
}

ImageBrush 画刷只需要设置它的ImageSource 属性,其它的属性都是从它的基类TileBrush继承而来

案例:

 <Grid x:Name="grid">
        <Grid.Background>
            <ImageBrush ImageSource="/Images/lyf.png" 
                    Stretch="UniformToFill"                     
                    TileMode="Tile">
                <ImageBrush.Viewport>
                    <Rect X="0" Y="0" Width="1" Height="1"/>
                </ImageBrush.Viewport>
            </ImageBrush>
        </Grid.Background>
    </Grid>

在上面的代码中,我们给Grid控件设置了一个ImageBrush 图像画刷,并设置Stretch为UniformToFill,即自适应填充,同时设置了Viewport。那么它运行之后呈现的效果如下:

此时的Grid的背景其实就是一张图片。我们给Window对象的MouseWheel事件订阅了一个回调函数,并在其实改变了Viewport的宽度和高度。滚动鼠标的滚轮,此时Grid的背景图像的填充将会呈现如下的样子:

private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
{
    double offset = e.Delta / 3600.0;
    ImageBrush imageBrush = grid.Background as ImageBrush;
    Rect rect = imageBrush.Viewport;
    if (rect.Width + offset <= 0 && rect.Height + offset <= 0)
        return;
 
    rect.Width += offset;
    rect.Height += offset;
    imageBrush.Viewport = rect;
}

 

标签:13,set,画刷,DependencyProperty,get,渐变,static,Brush,public
From: https://www.cnblogs.com/MingQiu/p/18001354

相关文章

  • [stable/nginx-ingress] [emerg] 46#46: bind() to 0.0.0.0:80 failed (13: Permissio
    该报错与nginx的报错是一样的,不同的是发生在kubernetes-ingress场景。使用NginxIngressController时,以Deployment的方式启动POD时会报错。使用的Deployment配置示例:https://github.com/nginxinc/kubernetes-ingress/blob/main/deployments/deployment/nginx-ingress.yaml这......
  • 20240130
    Kotlin编程知识总结总结自《Android第一行代码》变量varval可变变量不可变变量自动类型推导:vala=10显式声明类型:vala:Int=10函数关键词funfunmethodName(param1:Int,param2:Int):Int{ return0}语法糖funmethodName(param1:Int,param2:Int):......
  • CF138A Literature Lesson
    原题传送门分析既然题目要求求出所有四行诗共同的形态,那我们就想到可以用位运算。我们用二的次方来表示每一种形态,然后把每一篇诗的形态或起来,就可以得到最终的形态。输出的时候再拿个函数转一下就行了。有了基本框架,我们就可以开始构造特殊情况。题目中说到如果有aaaa这种......
  • C Primer Plus 中文第6版 10.13 第11题
    题目:编写一个程序,声明一个int类型的3*5二维数组,并用合适的值初始化它。该程序打印数组中的值,然后各值翻倍(即是原来的2倍),并显示出各个元素的新值。编写一个函数显示数组的内容,再编写一个函数把各元素的翻倍。这两个函数都以函数名和行数作为参数。分析:写2个函数即可。翻倍函数,用于使......
  • 13.测试计划
    用来描述一个压力/性能测试脚本和场景设计的基本运行单元,使用JMeter进行测试的所有内容都是基于一个测试计划用户定义变量独立运行每个线程组不勾选:各个线程组并行、随机执行勾选:线程组按照前后顺序来执行主线程组运行完成之后运行tearDown线程组函数测试模式,比如保存响应......
  • 20240131
    A.选车站枚举\(x_i<0\)可以\(\mathcal{O}(\sqrt{x_i})\)的计算出最小的\(x_j>0\)使得\(-x_ix_j\)为一个平方数,再枚举倍数即可//Author:xiaruize#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineullunsignedlonglong#defineALL(a......
  • 0131取Data路径下的文件
      f'{Path(file).resolve().parent.parent}{os.path.sep}data{os.path.sep}{name}' 这句话是Python代码,它使用了几个模块和方法来构造一个文件系统路径。下面我们逐个分解这行代码:Path(__file__):这里使用了Path类,它来自Python的pathlib模块,使得文件系统路径操作更加易于处......
  • 杂题20240131
    CF1753C思路点拨考虑一共有\(s\)个\(0\),\(n-s\)个\(1\)。最终序列的形态就是\(s\)个\(0\)在最前面,后面全部都是\(1\)。考虑在前\(s\)个位置中有\(k\)个\(1\),那么只需要将这\(k\)个\(1\)移动到后面就可以了。考虑第一次有效操作的概率,有\(\dfrac{n(n-1)......
  • 算法模板 v1.6.1.20240131
    算法模板v1.1.1.20240115:之前的历史版本已经不可寻,创建了第一份算法模板。v1.2.1.20240116:删除“编译”-“手动开栈”与“编译”-“手动开O优化”;将“编译”-“CF模板”中的第20行代码cin>>T;注释;删除“读写”及其目录下的内容;删除“图论”-“欧拉图”-“混合图”;删除“图论”-......
  • createDelegatingPasswordEncoder只有在spring 5.1.13才能用吗?
    springboot和spring版本对应关系:SpringBoot1.x支持SpringFramework4.x系列,包括4.0、4.1、4.2和4.3等版本。SpringBoot2.x支持SpringFramework5.x系列,包括5.0、5.1和5.2等版本。 下载springboot会一并下载 ......