Fillプロパティ(Brush)

 EllipseやRectangleオブジェクトのFillプロパティは図形内部を塗りつぶすBrushというクラスを指定している だけです。今回はこのBrushクラスに着目して説明を進めたいと思います。

 Brushクラス

 Brushクラスには次の派生クラスがあります。
ブラシ 説明
SolidColorBrush 均一な色の単色なブラシ
LinearGradientBrush 線形グラデーションで領域を塗りつぶすブラシ
RadialGradientBrush 放射状グラデーションで領域を塗りつぶすブラシ
ImageBrush イメージで領域を塗りつぶすブラシ
DrawingBrush Drawingで領域を塗りつぶすブラシ
VisualBrush Visualで領域を塗りつぶすブラシ

 DrawingBrushとVisualBrushは、説明しなければいけないことが一杯あるため、今回は割愛して残りの4つを説明します。

SolidColorBrush
 次のXAMLの例では、赤く塗りつぶす単純はFillプロパティを使って四角を描いています。

<Rectangle Width="100" Height="100" Fill="Red" />

この場合のFillプロパティは、実際には赤色のSolidColorBrushを使用しています。これは次のXAMLと同じことです。
 XAMLファイル(brush1.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush1" Height="300" Width="300">
   <Grid>
   <!-- これ以下のことと同じことです。-->
    <Rectangle Width="100" Height="100">
      <Rectangle.Fill>
        <SolidColorBrush Color="Red" />
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush1.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())



LinearGradientBrushBrush
 LinearGradientBrushは、線形グラデーションを使って領域を塗りつぶします。Defaultのグラデーションは、正規化した 四角形、つまり左上隅が(0,0)で右下隅が(1,1)の四角形を使用して定義されます。要するにグラデーションは、四角形の左上から 右下に変化するものとして定義されます。各点での色を指定することで2色間のグラデーションを描画します。
 具体的な例を見たほうが早いですね。
 XAMLファイル(brush2.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush2" Height="300" Width="300">
   <Grid>
    <Rectangle Height="200" Width="200">
      <Rectangle.Fill>
        <LinearGradientBrush>
          <GradientStop Color="Red" Offset="0"/>
          <GradientStop Color="GreenYellow" Offset="1" />
        </LinearGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush2.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())


 上の例ではグラデーションの開始位置(Offset=0)を赤色。グラデーションの終了位置(Offest=1)を黄緑色に指定しています。 そしてグラデーションの開始位置の左上が赤色、終了位置の右下が黄緑色になっているのが確認できたと思います

■グラデーションの方向の変更
 グラデーションはDefaltのままでは左上が開始位置、右下が終了位置ということは変わりません。そのため開始位置と 終了位置を変更することでグラデーションの方向を変更できます。開始位置、終了位置の変更にはStartPoint、EndPoint属性を 使用します。
 次の例ではグラデーションは横方向になります。
 XAMLファイル(brush3.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush3" Height="300" Width="300">
   <Grid>
    <Rectangle Height="200" Width="200">
      <Rectangle.Fill>
        <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
          <GradientStop Color="Red" Offset="0"/>
          <GradientStop Color="GreenYellow" Offset="1" />
        </LinearGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush3.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())



■グラデーション色を追加
 今まで例は、グラデーション色は最低の2の場合です。他のグラデーション色を追加してグラデーションを制御することが できます。
 次の場合は3色を定義しています。
 XAMLファイル(brush4.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush4" Height="300" Width="300">
   <Grid>
    <Rectangle Height="200" Width="200">
      <Rectangle.Fill>
        <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
          <GradientStop Color="Red" Offset="0"/>
          <GradientStop Color="Yellow" Offset="0.5" />
          <GradientStop Color="Cyan" Offset="1" />
        </LinearGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush4.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())



■グラデーション色の位置を変更
 グラデーション色の位置を変更するには、Offsetパラメータを使います。具体的にはグラデーション色をStartPointに 近づけるにはOffset値を0に近い値にすればいいし、EndPointに近づけるには1に近い値にすればいいんです。
 例えば次のようにすれば、前回の例に比べて黄色の位置が変わります。
 XAMLファイル(brush5.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush5" Height="300" Width="300">
   <Grid>
    <Rectangle Height="200" Width="200">
      <Rectangle.Fill>
        <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
          <GradientStop Color="Red" Offset="0"/>
          <GradientStop Color="Yellow" Offset="0.7" />
          <GradientStop Color="Cyan" Offset="1" />
        </LinearGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush5.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())



RadialGradientBrush
 RadialGradientBrushは、LinearGradientBrushと似ていますが、放射状のグラデーションを定義するもので、開始が グラデーションの円の中心で、終了が外縁になります。
 例を見ればすぐわかるので見てください。
 XAMLファイル(brush6.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush6" Height="300" Width="300">
   <Grid>
    <Rectangle Height="175" Width="250">
      <Rectangle.Fill>
        <RadialGradientBrush >
          <GradientStop Color="Yellow" Offset="0" />
          <GradientStop Color="Red" Offset="1" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush6.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())



■グラデーション中心の位置を変更
 RadialGradientBrushでは、GradientOroginプロパティを使用してグラデーションの中心の位置を変更できます。 通常、グラデーションの中心は円の中心ですが、中心位置は四角形の正規化された領域で指定します。したがって、 中心を左上隅に設定するにはGradientOriginを(0,0)に設定し、右隅にするにはGradientOriginを(1,1)に設定します。
 例えば次のようにすれば、グラデーション中心の位置が変わります。
 XAMLファイル(brush7.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush7" Height="300" Width="300">
   <Grid>
    <Rectangle Height="175" Width="250">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.2,0.5">
          <GradientStop Color="Blue" Offset="0" />
          <GradientStop Color="Red" Offset="1" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush7.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())



■楕円の中心の位置を変更
 GradientOriginによってグラデーション中心の位置を変更することはわかったけれど、グラデーションによって発生 する楕円自体の外縁は移動しません。この楕円自体の中心はCenterプロパティで設定することができます。
 次の例では、グラデーション楕円の位置が変更されたようになります。
 XAMLファイル(brush8.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush8" Height="300" Width="300">
   <Grid>
    <Rectangle Height="175" Width="250">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.2,0.5" Center="0.2,0.5">
          <GradientStop Color="Blue" Offset="0" />
          <GradientStop Color="Red" Offset="1" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush8.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())



■SpreadMethodプロパティ
 SpreadMethodプロパティはグラデーションを繰り返す方法を指定できます。 SpreadMethodプロパティに指定できる値は、Pad、Reflect、Repeatの3つです。
 このパラメータはRadialGradientBrushだけでなく、LinerGradientBrushでも使えます。
 でもグラデーションの繰り返すってなんだかわからないですよね。そこでまず例を見てください
 XAMLファイル(brush9.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush9" Height="300" Width="300">
   <Grid>
    <Rectangle Stroke="Black" Height="70" Width="130"
      Margin="5,5,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
      <Rectangle.Fill>
        <LinearGradientBrush SpreadMethod="Pad"
          StartPoint="0.3,0.5" EndPoint="0.7,0.5">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </LinearGradientBrush>
      </Rectangle.Fill>
    </Rectangle>

    <Rectangle Stroke="Black" Height="70" Width="130"
      Margin="5,85,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
      <Rectangle.Fill>
        <LinearGradientBrush SpreadMethod="Reflect"
          StartPoint="0.3,0.5" EndPoint="0.7,0.5">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </LinearGradientBrush>
      </Rectangle.Fill>
    </Rectangle>

    <Rectangle Stroke="Black" Height="70" Width="130"
      Margin="5,166,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
      <Rectangle.Fill>
        <LinearGradientBrush SpreadMethod="Repeat"
          StartPoint="0.3,0.5" EndPoint="0.7,0.5">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </LinearGradientBrush>
      </Rectangle.Fill>
    </Rectangle>

    <Rectangle Stroke="Black" Height="70" Width="130"
      Margin="145,5,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
      <Rectangle.Fill>
        <RadialGradientBrush SpreadMethod="Pad">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>

    <Rectangle Stroke="Black" Height="70" Width="130"
      Margin="145,85,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
      <Rectangle.Fill>
        <RadialGradientBrush SpreadMethod="Reflect">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>

    <Rectangle Stroke="Black" Height="70" Width="130"
      Margin="145,166,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
      <Rectangle.Fill>
        <RadialGradientBrush SpreadMethod="Repeat">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush9.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())


XAMLファイルが結構長くなってしまったので、実行した画面をみながら、説明を読んでください。
 6つの四角形がWindowの中にありますが、左がLinerGradientBrushで塗りつぶしたもの、右がRadialGradientBrushで 塗りつぶしたものです。左右どちらも上からSpreadMethodプロパティを"Pad"、"Reflect"、"Repeat"に それぞれ設定しました。LinearGradientBrushを使った例を使って説明します。
 左上の四角形に着目してみてください。XAML文を見てもらえばわかりますが、グラデーションの横に向かって描かれています。 そのStartPointの横方向は0.3、EndPointは0.7です。そうすると疑問になるのが、0〜0.3と0.7〜1の余白の領域はどうするのか。 それを設定するのがSpreadMethodプロパティになります。
 "Pad"はGradientStopで指定した色で余白の領域を塗りつぶします。
 "Reflect"は反転させたグラデーションで余白の領域を塗りつぶします。
 "Repeat"は同じグラデーションの繰り返しで余白の領域を塗りつぶします。
 RadialGradientBrushも同様です。RadientGradientBrushの場合、普通楕円形状が終端です。そうすると四隅に残った余白をどうするかと SpreadMethodプロパティで設定します。

■RadientGradientBrushの半径を設定
 RadiusX、RadiusYプロパティを使用して、グラデーションの半径を指定できます。Default値は0.5です。 0.5より小さい値を用いた場合には、SpreadMethodプロパティの設定によって余白が埋められます。逆に 0.5より大きい場合は、グラデーションをズームした効果が得られます。
 例を見てください
 XAMLファイル(brush10.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush10" Height="300" Width="300">
   <Grid>
    <Rectangle Stroke="Black" Height="100" Width="250"
      Margin="5,5,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
      <Rectangle.Fill>
        <RadialGradientBrush
          RadiusX="0.1" RadiusY="0.1">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>

    <Rectangle Stroke="Black" Height="100" Width="250"
      Margin="5,120,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
      <Rectangle.Fill>
        <RadialGradientBrush SpreadMethod="Reflect"
          RadiusX="0.1" RadiusY="0.1">
          <GradientStop Color="Black" Offset="0" />
          <GradientStop Color="White" Offset="1" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
  </Grid>
</Window>

 スクリプトファイル

import wpf

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush10.xaml')
  

if __name__ == '__main__':
  Application().Run(MyWindow())


 スクリプトを実行すると2つの四角形が表示されます。上の四角形は半径0.1を使用したRadialGradientBrushで塗りつぶされています。 また下の四角形はSpreadMethodプロパティの"Reflect"と組み合わせて設定した場合を示しています。

ImageBrush
 ImageBrushを使用すると領域を画像で塗りつぶすことができます。Defaultの動作では図形の大きさに合わせて、 ブラシが引き伸ばされるため、画像の縦横比は維持されません。次の例では四角形の内部を画像で塗りつぶしています。
 XAMLファイル(brush11.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush11" Height="300" Width="300">
   <Grid>
    <Rectangle Height="150" Width="250">
      <Rectangle.Fill>
        <ImageBrush x:Name="image1"/>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf
import System
from System import Uri, UriKind
from System.Windows.Media.Imaging import BitmapImage

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush11.xaml')
    self.image1.ImageSource = BitmapImage(Uri("/cake.jpg", UriKind.Relative))
  

if __name__ == '__main__':
  Application().Run(MyWindow())


 XAML文の中でImageBrushタグのImageSource属性として"cake.jpg"を指定してもよかったのですが、 絶対URIで指定することはできても、相対URIで指定することができませんでした。Bugでしょうか? 取りあえず、スクリプトで逃げて、相対URIで指定しました。
※絶対URI・・・"C:\cake.jpg"や"file///c:/cake.jpg"のように指定して
        ファイルの絶対的な所在を記述する方法
 相対URI・・・"/image/cake.jpg"、"../cake.jpg"、"cake.jpg"というように
        参照するフォルダからの相対的な 所在を記述する方法

■Stretchプロパティ
 Stretchプロパティを変更すると図形に合わせて、画像が伸縮する方法を変更することができます。
 例を見てみましょう。
 XAMLファイル(brush12.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush12" Height="420" Width="580">
  <Grid>
    <Rectangle Height="150" Width="250" VerticalAlignment="Top" HorizontalAlignment="Left"
      Margin="20,20,0,0">
      <Rectangle.Fill>
        <ImageBrush Stretch="None" x:Name="image1"/>
      </Rectangle.Fill>
    </Rectangle>
    <Rectangle Height="150" Width="250" VerticalAlignment="Top" HorizontalAlignment="Left"
      Margin="300,20,0,0">
      <Rectangle.Fill>
        <ImageBrush Stretch="Uniform" x:Name="image2"/>
      </Rectangle.Fill>
    </Rectangle>
    <Rectangle Height="150" Width="250" VerticalAlignment="Top" HorizontalAlignment="Left"
      Margin="20,200,0,0">
      <Rectangle.Fill>
        <ImageBrush Stretch="UniformToFill" x:Name="image3"/>
      </Rectangle.Fill>
    </Rectangle>
    <Rectangle Height="150" Width="250" VerticalAlignment="Top" HorizontalAlignment="Left"
      Margin="300,200,0,0">
      <Rectangle.Fill>
        <ImageBrush Stretch="Fill" x:Name="image4"/>
      </Rectangle.Fill>
    </Rectangle>
    <TextBlock Height="20" HorizontalAlignment="Left" Margin="20,175,0,0" Text="None"
      TextAlignment="Center" VerticalAlignment="Top" Width="250" />

    <TextBlock Height="20" HorizontalAlignment="Left" Margin="300,175,0,0" Text="Uniform"
      TextAlignment="Center" VerticalAlignment="Top" Width="250" />

    <TextBlock Height="20" HorizontalAlignment="Left" Margin="20,355,0,0" Text="UniformToFill"
      TextAlignment="Center" VerticalAlignment="Top" Width="250" />

    <TextBlock Height="20" HorizontalAlignment="Left" Margin="300,355,0,0" Text="Fill ( Default )"
      TextAlignment="Center" VerticalAlignment="Top" Width="250" />
  </Grid>
</Window>

 スクリプトファイル

import wpf
import System
from System import Uri, UriKind
from System.Windows.Media.Imaging import BitmapImage

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush12.xaml')
    self.image1.ImageSource = BitmapImage(Uri("/cake.jpg", UriKind.Relative))
    self.image2.ImageSource = self.image1.ImageSource
    self.image3.ImageSource = self.image1.ImageSource
    self.image4.ImageSource = self.image1.ImageSource

if __name__ == '__main__':
  Application().Run(MyWindow())


 上の例のように、Stretchプロパティには4種類の設定があります。
Stretchプロパティ 説明
None 何も伸縮せず、そのまま画像が描かれます。
Uniform 図形の中に画像が納まるように伸縮します。縦横比は維持されます。
UniformToFill 図形の中を画像で埋めるように伸縮します。画像がはみ出しても気にしません。
縦横比は維持されます。
Fill 図形の中を画像で埋めるように伸縮します。縦横比は維持しません。
(Default値)


■画像の配置を変更
 画像の配置は、AlignmentXプロパティで左端、中央、右端に、AlignmentYプロパティで上端、中央、下端に変更できます。 但し、StretchプロパティをNoneにしているときのみ有効ですので、注意してください。
 例では画像が四角形の右下に合わせて配置されます。
 XAMLファイル(brush13.xaml)

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="brush13" Height="300" Width="300">
   <Grid>
    <Rectangle Height="150" Width="250">
      <Rectangle.Fill>
        <ImageBrush x:Name="image1" Stretch="None"
          AlignmentX="Right" AlignmentY="Bottom"/>
      </Rectangle.Fill>
    </Rectangle>
   </Grid>
</Window>

 スクリプトファイル

import wpf
import System
from System import Uri, UriKind
from System.Windows.Media.Imaging import BitmapImage

from System.Windows import Application, Window

class MyWindow(Window):
  def __init__(self):
    wpf.LoadComponent(self, 'brush13.xaml')
    self.image1.ImageSource = BitmapImage(Uri("/cake.jpg", UriKind.Relative))
  

if __name__ == '__main__':
  Application().Run(MyWindow())