WisdomSoft - for your serial experiences.

4.3 長方形と円

基本的な図形である長方形と円を描画し、図の塗りつぶしや輪郭線の描画を解説します。

4.3.1 内部を塗りつぶす

Line オブジェクトは 1 本の線を表すため、図形の内側という概念を持ちませんでしたが、長方形や円などの閉じた図形は、図形の内部と輪郭という概念を持ちます。輪郭線に関しては Line オブジェクトと同じ扱いですが、内部は輪郭線とは別のブラシを用いて塗りつぶされます。

まず、最も単純な閉じた図形である長方形を描画してみましょう。長方形は System.Windows.Shapes.Rectangle クラスで表します。

System.Windows.Shapes.Rectangle クラス
System.Object 
   System.Windows.Threading.DispatcherObject 
     System.Windows.DependencyObject 
       System.Windows.Media.Visual 
         System.Windows.UIElement 
           System.Windows.FrameworkElement 
             System.Windows.Shapes.Shape 
              System.Windows.Shapes.Rectangle
public sealed class Rectangle : Shape

1 つの Rectangle オブジェクトが、画面上に表示される 1 つの長方形に対応します。このクラスのコンストラクタは、パラメータを受け取りません。

Rectangle クラスのコンストラクタ
public Rectangle ()

Rectangle のような閉じた図形の内部を塗りつぶすには Fill プロパティを利用します。Fill プロパティは Shape クラスで宣言されているものなので、Rectangle 以外の閉じた図形でも同じように利用することができます。

Shape クラス Fill プロパティ
public Brush Fill { get; set; }

Fill には、内部を塗りつぶす Brush オブジェクトを指定します。既定では null が設定されているので、内部は塗りつぶされません。適切な Brush オブジェクトを設定して塗りつぶしてください。

長方形の幅や高さは、Window クラスの幅や高さを設定したときと同様に、基底クラスである FrameworkElement の Width プロパティと Height プロパティを使用します。つまり、図形の幅や高さの設定方法は、コントロールと同じ操作方法で設定したり取得することができるということを意味します。

コード1
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

class Test {
	[STAThread]
	public static void Main() {
		Rectangle rect = new Rectangle();
		rect.Fill = Brushes.Red;
		rect.Width = 400;
		rect.Height = 200;
		Canvas.SetLeft(rect, 10);
		Canvas.SetTop(rect, 10);

		Canvas canvas = new Canvas();
		canvas.Children.Add(rect);

		Window wnd = new Window();
		wnd.Content = canvas;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード1 実行結果

コード1は、長方形を表示するために Rectangle オブジェクトを生成し、Fill プロパティに赤色で塗りつぶすことを表す Red ブラシを指定しています。実行結果を見ると、指定した幅と高さの長方形が表示されていることを確認できます。

Rectangle クラスでは、角の丸い長方形も容易に作成することができます。長方形の角の丸みは RadiusX プロパティRadiusY プロパティから設定します。

Rectangle クラス RadiusX プロパティ
[TypeConverterAttribute(typeof(LengthConverter))] 
public double RadiusX { get; set; }
Rectangle クラス RadiusY プロパティ
[TypeConverterAttribute(typeof(LengthConverter))] 
public double RadiusY { get; set; }

RadiusX は、水平方向に対する丸み、RadiusY は垂直方向に対する丸みです。これらのプロパティには、それぞれの方向に対して長方形の角を丸くする楕円状のピクセル数を指定します。もし、RadiusX が Width プロパティと同じ値であり、RadiusY が Height と同じ値であれば、長方形は完全な楕円形になります。もちろん、楕円形を表示するには別の専用のクラスがあるので、そのようなことを長方形を表す Rectangle クラスのオブジェクトで行う意味はありません。

コード2
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

class Test {
	[STAThread]
	public static void Main() {
		Rectangle rect = new Rectangle();
		rect.Fill = Brushes.Red;
		rect.Width = 400;
		rect.Height = 200;
		rect.RadiusX = 40;
		rect.RadiusY = 20;
		Canvas.SetLeft(rect, 10);
		Canvas.SetTop(rect, 10);

		Canvas canvas = new Canvas();
		canvas.Children.Add(rect);

		Window wnd = new Window();
		wnd.Content = canvas;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード2 実行結果

コード2は、コード1と同じ幅と高さの長方形を描画していますが、RadiusX と RadiusY プロパティの値を変更しているため、長方形の角が丸くなっています。よりリッチなユーザー・インタフェースを構築するには、角のとがった長方形よりも、全体的に丸みを帯びたデザインが多用されるため、こうした表現能力が必要になることもあるでしょう。

4.3.2 楕円

楕円形を描画する方法は、使用するクラスが異なるということ意外は Rectangle クラスとほとんど同じです。楕円系は System.Windows.Shapes.Ellipse クラスで表されています。

System.Windows.Shapes.Ellipse クラス
System.Object 
   System.Windows.Threading.DispatcherObject 
     System.Windows.DependencyObject 
       System.Windows.Media.Visual 
         System.Windows.UIElement 
           System.Windows.FrameworkElement 
             System.Windows.Shapes.Shape 
              System.Windows.Shapes.Ellipse
public sealed class Ellipse : Shape

このクラスのコンストラクタは、パラメータを受け取りません。

Ellipse クラスのコンストラクタ
public Ellipse ()

Ellipse オブジェクトを生成した後は、Rectangle クラスと同様に幅、高さ、内部を塗りつぶすブラシなどを設定して表示することができます。Ellipse オブジェクトは、幅と高さから割り出される長方形に外接する楕円を描画します。

コード3
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

class Test {
	[STAThread]
	public static void Main() {
		Ellipse ellipse = new Ellipse();
		ellipse.Fill = Brushes.Blue;
		ellipse.Width = 400;
		ellipse.Height = 200;
		Canvas.SetLeft(ellipse, 10);
		Canvas.SetTop(ellipse, 10);

		Canvas canvas = new Canvas();
		canvas.Children.Add(ellipse);

		Window wnd = new Window();
		wnd.Content = canvas;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード3 実行結果

コード3は、コード1とほとんど同じ内容のプログラムです。ただ Rectangle 型に代わって Ellipse 型を利用しているというだけで、利用するプロパティは Shape で共通しているので、それ以外の変化はありません。

4.3.3 輪郭線

長方形や楕円のような閉じた図形の輪郭線を描画したり、図形の内部は描画せずに長方形や楕円の線だけを描画したい場合は Fill プロパティを null の状態に設定し Stroke プロパティに適切な Brush オブジェクトを設定します。輪郭線の描画方法に関しては Line オブジェクトで解説した方法と同じなので Shape クラスで宣言されている Stroke 関連プロパティで、輪郭線の色や太さなどを自由に設定できます。

コード4
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

class Test {
	[STAThread]
	public static void Main() {		
		Rectangle rect = new Rectangle();
		rect.Stroke = Brushes.Black;
		rect.Width = 300;
		rect.Height = 150;
		Canvas.SetLeft(rect, 10);
		Canvas.SetTop(rect, 10);

		Ellipse ellipse = new Ellipse();
		ellipse.Stroke = Brushes.Red;
		ellipse.Width = 300;
		ellipse.Height = 150;
		Canvas.SetLeft(ellipse, 10);
		Canvas.SetTop(ellipse, 10);

		Canvas canvas = new Canvas();
		canvas.Children.Add(rect);
		canvas.Children.Add(ellipse);

		Window wnd = new Window();
		wnd.Content = canvas;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード4 実行結果

コード4は、同じ幅と高さの長方形と楕円を同じ座標に配置しています。実行結果を見ると、Ellipse の解説で前述したように楕円が長方形の各辺に接していることが確認できます。図形の内部は Fill プロパティが null なので塗りつぶされることはなく、Stroke に設定されている Brush の色で輪郭線が描画されています。

4.3.4 長方形を保存する

長方形も楕円など、一定の領域の範囲を要求する描画要素は、幅と高さを表す値を要求します。また、必要に応じて座標も指定する必要があります。このように、一般的に領域を表現する手段には長方形が用いられ、長方形は、座標とサイズから自らの領域を決定することができます。

Rectangle や Ellipse、その他のコントロールなども含めた描画要素は、自らの幅と高さを Width プロパティと Height プロパティで保持しています。これらの情報は個別のプロパティが用いられていますが、Point クラスと同様の理由で、幅と高さを情報として保持する場合は個別の変数として管理するのは非効率的です。

幅と高さを表す 2 つの値は System.Windows.Size 構造体でまとめることができます。Size 構造体は、型名やプロパティ名が異なるだけで、基本的な構造は Point 構造体と酷似しています。

System.Windows.Size 構造体
[SerializableAttribute] 
[TypeConverterAttribute(typeof(SizeConverter))] 
public struct Size : IFormattable

Size 構造体のコンストラクタには、幅と高さを表す値を渡します。

Size 構造体のコンストラクタ
public Size (double width, double height)

width には幅を表す値、height には高さを表す値を指定します。これらの値は Width プロパティHeight プロパティから設定・取得することができます。

Size 構造体 Width プロパティ
public double Width { get; set; }
Size 構造体 Height プロパティ
public double Height { get; set; }

これで、幅と高さを表す値を 1 つの変数で表現することができるようになります。

Point 構造体と Size 構造体の 2 つの値を組み合わせることで、長方形の座標とサイズを決定することができますが、座標とサイズは個別に扱わなければなりません。座標とサイズの組み合わせによって 1 つの長方形を表現する場合、やはりそれらの変数を個別に管理するのは非効率的です。このような場合は Point 構造体と Size 構造体を組み合わせた System.Windows.Rect 構造体を用いるべきです。

System.Windows.Rect 構造体
[SerializableAttribute] 
[TypeConverterAttribute(typeof(RectConverter))] 
public struct Rect : IFormattable

Rect 構造体のコンストラクタはいくつかにオーバーロードされています。この場では、代表的な 2 つのコンストラクタを紹介します。

Rect 構造体のコンストラクタ
public Rect (Point location, Size size)
public Rect (
    double x, double y,
    double width, double height
)

最初のコンストラクタは、座標を表す Point 構造体の値を location パラメータに、幅と高さを表す Size 構造体を size パラメータに渡します。2 番目のコンストラクタは、もっと単純です。x と y に座標を表す値を、width に幅、height に高さを表す値を直接指定することができます。

Rect 構造体が内部で管理している座標とサイズは Location プロパティと Size プロパティから設定・取得することができます。

Rect 構造体 Location プロパティ
public Point Location { get; set; }
Rect 構造体 Size プロパティ
public Size Size { get; set; }

この場では、割愛しますが、Rect 構造体は Point 構造体と Size 構造体と同様のプロパティも保有しています。直接の値で設定・取得を行いたい場合は X、Y、Width、Height プロパティを利用することもできます。