目次|前|次 |
java.awt.Graphics
を継承するGraphics2D
では、図形、テキストおよびイメージの表示について制御できる内容が、一段と高度なものになっています。Java 2Dのレンダリング処理は、Graphics2D
オブジェクトとその状態属性を使用して制御します。
Graphics2D
の状態属性には線のスタイルや変換などがあり、グラフィック・オブジェクトがレンダリングされるときに適用されます。Graphics2D
に関する状態属性の集合を、Graphics2D
コンテキストと呼びます。テキストや図形、イメージをレンダリングするには、Graphics2D
コンテキストを設定してから、draw
やfill
などのGraphics2D
レンダリング・メソッドを呼び出します。
次の表は、Graphics2D
コンテキストに関連して使用するインタフェースとクラスの一覧です。状態属性を表すクラスも含まれています。これらのほとんどのクラスは、java.awt
パッケージに含まれています。
インタフェース | 説明 |
---|---|
Composite |
基になるグラフィックス領域に描画プリミティブを合成するためのメソッドを定義します。AlphaComposite によって実装されます。 |
CompositeContext |
合成操作のためのカプセル化されて最適化された環境を定義します。プログラムで独自の合成規則を実装するときに使われます。 |
Paint |
スーパー・クラス: Transparency draw 操作またはfill 操作での色を定義します。Color 、GradientPaint およびTexturePaint によって実装されます。 |
PaintContext |
ペイント操作のためのカプセル化されて最適化された環境を定義します。プログラムで独自のペイント操作を実装するときに使われます。 |
Stroke |
レンダリングされるShape の輪郭線を囲むShape を生成します。BasicStroke によって実装されます。 |
クラス | 説明 |
---|---|
AffineTransform (java.awt.geom) |
ある2次元座標から別の2次元座標への線形マッピングを行う、2次元のアフィン変換を表します。 |
AlphaComposite |
インタフェース: Composite 図形、テキスト、イメージの基本的なアルファ合成規則を実装します。 |
BasicStroke |
インタフェース: Stroke Shape の輪郭線に適用される「ペンのスタイル」を定義します。 |
Color | インタフェース: Paint Shape に均一な塗りつぶしを定義します。 |
GradientPaint |
インタフェース: Paint Shape にカラーの線形グラデーションの塗りつぶしパターンを定義します。この塗りつぶしパターンは、点P1の色C1から点P2の色C2まで変化します。 |
Graphics2D |
スーパー・クラス: Graphics 2次元レンダリングの基本クラスです。元のjava.awt.Graphics クラスを継承しています。 |
TexturePaint |
インタフェース: Paint テクスチャまたはパターンを使用したShape の塗りつぶしを定義します。テクスチャやパターンは、BufferedImage から生成されます。 |
Java 2D APIを使用してグラフィック・オブジェクトをレンダリングするには、Graphics2D
コンテキストを設定してから、Graphics2D
レンダリング・メソッドの1つにグラフィック・オブジェクトを渡します。
Graphics2D
コンテキストを構成する状態属性を変更することで、次の操作が可能です。
Graphics2D
では、グラフィックス・コンテキストの属性を追加または変更するためのメソッドがいくつか定義されています。大部分のメソッドは、Paint
オブジェクトやStroke
オブジェクトなど、特定の属性を表すオブジェクトを受け取ります。
Graphics2D
コンテキストは、このような属性オブジェクトの参照を保持します。Graphics2D
コンテキストに含まれる属性オブジェクトを変更する場合は、適切なset
メソッドを呼び出して、コンテキストに通知する必要があります。レンダリング操作の間に属性オブジェクトを変更すると、予測できない動作をしたり、場合によっては動作が不安的になります。
グラフィック・オブジェクトのレンダリングでは、幾何学的図形、イメージおよび属性の情報がまとめられて、ディスプレイ上で変更する必要のあるピクセル値が算出されます。
Shape
のレンダリング処理は、4つのステップに分けることができます。
Shape
をストロークで描画する必要がある場合は、Graphics2D
コンテキストのStroke
属性を使用して、描画されるパスを囲む新しいShape
を生成します。Graphics2D
コンテキストの変換属性に従って、Shape
のパスの座標をユーザー空間からデバイス空間に変換します。Graphics2D
コンテキストのクリッピング属性を使用して、Shape
のパスをクリッピングします。Shape
に残り部分がある場合は、Graphics2D
コンテキストのPaint
属性とComposite
属性を使用して塗りつぶします。テキストのレンダリングは、Shape
のレンダリングとほぼ同じです。テキストは個別のグリフとしてレンダリングされて、グリフはそれぞれがShape
になります。唯一の違いは、Java 2D APIはレンダリングの前に、テキストに適用されるFont
を判別し、Font
から適切なグリフを取得する必要があることです。
イメージの処理はテキストや図形と異なり、変換操作とクリッピング操作はイメージのバウンディング・ボックスに対して行われます。色の情報はイメージ自体から取り出されて、イメージのピクセルがレンダリング面に合成される際は、色情報のアルファ・チャネルがそのときのComposite
属性とともに使われます。
Java 2D APIでは、速度と品質のどちらを優先してオブジェクトをレンダリングするか指定できます。優先情報は、Graphics2D
コンテキストのRenderingHints
属性を使用してヒントとして指定します。レンダリング・モードの変更に対応していないプラットフォームもあるため、指定したレンダリング・ヒントが必ず使われるとはかぎりません。
RenderingHints
クラスは、次の種類のヒントをサポートしています。
Graphics2D
コンテキストのRenderingHints
属性を設定または変更するには、setRenderingHints
を呼び出します。ヒントをデフォルトに設定すると、プラットフォームでのレンダリングのデフォルト設定が使われます。
アンチエイリアス
グラフィックス・プリミティブをラスター・グラフィックス・ディスプレイ装置にレンダリングすると、エイリアス化のために縁がギザギザになる場合があります。弧や対角線の場合、直線や曲線の経路にもっとも近いピクセルをオンにして近似表現するので、ギザギザした表示になります。解像度の低い装置ではこの現象が特に顕著になるため、水平や垂直の線の滑らかな縁に対し、ギザギザの縁が際立って見えてしまいます。
アンチエイリアスは、オブジェクトの縁を滑らかにレンダリングするために使われる技法です。単純に直線や曲線にもっとも近いピクセルをオンにするのではなく、レンダリングされる形状によってカバーされる領域の大きさに比例して、周囲のピクセルの輝度が設定されます。これによって、オブジェクトの縁が鋭くなくなり、複数のピクセルにまたがってオンからオフへと移行するようになります。ただし、アンチエイリアスを行うと必要なコンピュータ・リソースが増えるため、レンダリングの速度が遅くなる場合があります
。
GeneralPath
オブジェクトのようなShape
をストロークで描画することは、GeneralPath
のセグメントに沿って論理的なペンを走らせることに相当します。Graphics2D
のStroke
属性は、ペンによって描画される軌跡の特性を定義するものです。
Graphics2D
コンテキストのストローク属性を定義するには、BasicStroke
オブジェクトを使用します。BasicStroke
では、線の幅、線端のスタイル、セグメントの接合スタイル、破線パターンなどの特性が定義されています。Graphics2D
コンテキストのStroke
属性を設定または変更するには、setStroke
を呼び出します。
たとえば、図2-3の最初のイメージはマイター接合スタイルを使用しており、2 番目のイメージはラウンド接合スタイル、丸めた線端スタイルおよび破線パターンを使用しています。
Stroke
属性を使用するGraphics2D
レンダリング・メソッドは、draw
、drawArc
、drawLine
、drawOval
、drawPolygon
、drawPolyline
、drawRect
およびdrawRoundRect
です。これらのメソッドを呼び出すと、指定したShape
の輪郭がレンダリングされます。Stroke
属性は線の特性を定義し、Paint
属性はペンによって描画される軌跡の色とパターンを定義するものです。
たとえば、draw(myRectangle)
を呼び出すと、次のようになります。
Stroke
が適用されます。Shape
オブジェクトに変換されます。Shape
の外形の内側にあるピクセルに、Paint
が適用されます。この処理を示しているのが図2-4です。
Graphics2D
コンテキストの塗りつぶし属性は、Paint
オブジェクトで表されます。Graphics2D
コンテキストにPaint
オブジェクトを追加するには、setPaint
メソッドを呼び出します。
Shape
またはグリフを描画すると(Graphics2D.draw
、Graphics2D.drawString
)、ストロークで描画されたオブジェクトの輪郭線を表すShape
の内側にあるすべてのピクセルに、Paint
が適用されます。Shape
を塗りつぶすと(Graphics2D.fill
)、Shape
の外形の内側にあるすべてのピクセルに、Paint
が適用されます。
単純な均一の塗りつぶしは、setColor
メソッドで設定できます。Color
は、Paint
インタフェースのもっとも簡単な実装です。
グラデーションやテクスチャのようなさらに複雑な描画スタイルでShape
を塗りつぶすには、Java 2DのPaint
インタフェースのGradientPaint
クラスとTexturePaint
クラスを使用します。単純な1色塗りで複雑な塗りつぶしを行おうとすると時間のかかる作業になりますが、これらのクラスを使用すると手間のかかる作業は必要なくなります。図2-5に示す2種類の塗りつぶしは、GradientPaint
とTexturePaint
で簡単に定義できます。
fill
を呼び出してShape
をレンダリングすると、システムでは次の処理が行われます。
Shape
を構成するピクセルを特定します。Paint
オブジェクトから各ピクセルの色を取得します。バッチ処理
ピクセルを効率よく処理するため、Java 2D APIはバッチでピクセルを処理します。特定の走査線の連続したピクセル群またはピクセルのブロックをバッチ処理できます。このバッチ処理は、2つのステップで行われます。
Paint
オブジェクトのcreateContext
メソッドを呼び出し、PaintContext
を作成します。PaintContext
には、現在のレンダリング操作についてのコンテキスト情報と、色の生成に必要な情報が格納されます。createContext
メソッドには、塗りつぶしの対象となっているグラフィックス・オブジェクトのユーザー空間とデバイス空間におけるバウンディング・ボックス、色の生成に使われるColorModel
およびユーザー空間からデバイス空間へのマッピングで使われる変換が渡されます。任意のColorModel
をサポートできないPaint
オブジェクトもあるので、ColorModel
はヒントとして扱われます。ColorModels
の詳細は、「色」を参照してください。getColorModel
メソッドを呼び出して、生成された塗りつぶし色のColorModel
をPaintContext
から取得します。次に、getRaster
メソッドを繰り返し呼び出して、各バッチの実際の色データを含むRaster
を取得します。この情報はレンダリング・パイプラインの次の段階に渡されて、そこでは、生成された色が現在のComposite
オブジェクトを使用してレンダリングされます。
クリッピング・パスは、Shape
またはImage
の中のレンダリングが必要な部分を示すものです。Graphics2D
コンテキストにクリッピング・パスが含まれている場合、Shape
またはImage
で実際にレンダリングされるのは、クリッピング・パスの内側にある部分だけです。
Graphics2D
コンテキストにクリッピング・パスを追加するには、setClip
メソッドを呼び出します。任意のShape
を使用して、クリッピング・パスを定義できます。
クリッピング・パスを変更するには、setClip
を使用して新しいパスを指定するか、clip
を呼び出して、古いクリッピング・パスと新しいShape
の交差部分を新しいクリッピング・パスにします。
Graphics2D
コンテキストに含まれている変換は、レンダリングでユーザー空間からデバイス空間にオブジェクトを変換するときに使われます。回転や拡大縮小など、これ以外の変換を行うには、その変換をGraphics2D
コンテキストに追加します。追加した変換は、レンダリングの際に適用される変換のパイプラインの一部になります。
Graphics2D
では、Graphics2D
コンテキストの変換を変更する方法がいくつか提供されています。もっとも簡単な方法は、Graphics2D
の変換メソッドrotate
、scale
、shear
またはtranslate
のいずれかを呼び出すことです。レンダリングで適用する変換の特性を指定すると、Graphics2D
が自動的に適切な変更を行います。
現在のGraphics2D
の変換に、AffineTransform
を明示的に連結することもできます。AffineTransform
は、グラフィックス・プリミティブのセットに対し、平行移動、拡大縮小、回転、変形などの線形変換を行います。既存の変換に新しい変換を連結すると、指定した最後の変換が最初に適用されます。現在の変換に新しい変換を連結するには、Graphics2D.transform
にAffineTransform
を渡します。
Graphics2D
クラスにはsetTransform
メソッドも含まれますが、既存の変換に別の座標変換を連結する場合にはこのメソッドを使用しないでください。setTransform
メソッドはGraphics2D
オブジェクトの現行の変換を上書きします。この機能は、次のような操作を行う場合に必要です。
JComponent
をペイントするGraphics2D
オブジェクトの供給者が、レンダリングの変換で効果を得る可能性がある他のすべての状況。setTransform
メソッドは、変換したグラフィックス、テキストまたはイメージのレンダリング後に、Graphics2D
オブジェクトを元の変換に戻す場合に使用します。
Graphics2D
では、パラメータとしてAffineTransform
を受け取る形式のdrawImage
メソッドも提供されています。このメソッドを使用すると、変換のパイプラインを永続的に変更しなくても、イメージ・オブジェクトを描画するときに目的の変換を適用できます。イメージは、Graphics2D
コンテキストの現在の変換に新しい変換を連結した場合と同じように描画されます。
アフィン変換
Java 2D APIでは、AffineTransform
という変換クラスが提供されています。AffineTransform
を使用して、レンダリングの際のテキスト、図形およびイメージの変換が行われます。Font
オブジェクトに変換を適用し、新しいフォント派生を作成することもできます。詳細については、「フォント派生の作成」を参照してください。
アフィン変換は、グラフィックス・プリミティブのセットに対して線形の変換を行います。直線は直線に、平行線は平行線に、常に変換されますが、点の間の距離および平行ではない線の間の角度は変わります。
アフィン変換は、次の形式の2次元行列に基づいて行われます。
ここでは、
および
です
変換を組み合わせることで、オブジェクトに適用できる一連の変換群、つまり変換のパイプラインを効果的に作成できます。この組合せのことを連結と呼びます。AffineTransform.concatenate
などの既存の変換に新しい変換を連結すると、最後に指定した変換が最初に適用されます。既存の変換に、新しい変換を前連結することもできます。この場合は、最後に指定した変換が最後に適用されます。
前連結は、ユーザー空間ではなくデバイス空間に関係する変換を行うために使用します。たとえば、絶対ピクセル空間に関係する変換を実行するには、AffineTransform.preConcatenate
を使用します。
AffineTransform
では、AffineTransform
オブジェクトを構築するための便利なメソッド群が提供されています。
getTranslateInstance
getRotateInstance
getScaleInstance
getShearInstance
これらのメソッドを使用して、作成する変換の特性を指定すると、AffineTransform
が適切な変換行列を生成します。変換行列の要素を直接指定して、AffineTransform
を作成することもできます。
2つのグラフィック・オブジェクトが重なる場合、重なった部分のピクセルをどのような色でレンダリングするかを決める必要があります。たとえば、赤い矩形と青い矩形を重ねる場合、2つの図形が共有するピクセルは、赤、青または2つの色の任意の組合せでレンダリングすることになります。重なる領域のピクセルの色により、どちらの矩形が上になっていて、どの程度透けて見えるかが決まります。重なるオブジェクトで共有されているピクセルをどのような色でレンダリングするか決める処理を、合成処理と呼びます。
Java 2Dの合成処理モデルの基礎になるインタフェースは、Composite
とCompositeContext
の2つです。
使用する合成スタイルを指定するには、setComposite
メソッドを呼び出して、Graphics2D
コンテキストにAlphaComposite
オブジェクトを追加します。Composite
インタフェースの実装であるAlphaComposite
では、様々な合成スタイルがサポートされています。このクラスのインスタンスは、既存の色と新しい色を混合する方法を記述した合成の規則を具体的に表しています。
AlphaComposite
クラスで使われるもっとも一般的な合成規則の1つはSRC_OVERで、これは、新しい色(ソース色)を既存の色(デスティネーション色)の上に混合するように指定するものです。
AlphaCompositeの合成規則 | 説明 |
---|---|
CLEAR | クリア |
DEST_IN | デスティネーションが内側 |
DEST_OUT | デスティネーションが外側 |
DEST_OVER | デスティネーションが上 |
SRC | ソース |
SRC_IN | ソースが内側 |
SRC_OUT | ソースが外側 |
SRC_OVER | ソースが上 |
色のアルファ値は透明度の単位です。この値は、色を重ねたときに前にレンダリングされている色がどの程度透けて見えるかを、パーセントで示します。不透明な色(alpha=1.0
)は下になっている色をまったく通さず、透明な色(alpha=0.0
)は下の色を完全に通します。
テキストとShape
のレンダリングでは、アルファ値はGraphics2D
コンテキストのPaint
属性から導出されます。Shape
とテキストがアンチエイリアス処理される場合は、Graphics2D
コンテキストのPaint
属性から得られるアルファ値は、ラスター化されたパスからのピクセル・カバレージ情報と結合されます。イメージは独自のアルファ情報を保持しています。詳細については、「透明度とイメージ」を参照してください。
AlphaComposite
オブジェクトを作成する際に、アルファ値を追加指定できます。このAlphaComposite
オブジェクトをGraphics2D
コンテキストに追加すると、追加したアルファ値により、レンダリングされるグラフィック・オブジェクトの透明度が大きくなります。つまり、各グラフィック・オブジェクトのアルファ値に、AlphaComposite
のアルファ値が掛けられます。
イメージには、イメージ内の各ピクセルに対する透明度の情報を持たせることができます。アルファ・チャネルと呼ばれるこの情報は、イメージと既存の描画結果を混合するために、Graphics2D
コンテキストのe Composite
オブジェクトと組み合わせて使われます。
たとえば、図2-6は、異なる透明度情報を持つ3種類のイメージです。どの場合も、イメージは青い矩形に重ねて表示されます。この例では、Graphics2D
コンテキストは、合成操作としてSRC_OVERを使用するAlphaComposite
オブジェクトを含んでいるものとします。
最初のイメージでは、すべてのピクセルが完全に不透明(犬の体)または完全に透明(背景)になっています。このような効果は、Webページでよく使われます。2番目のイメージでは、犬の体の全ピクセルを不透明ではない一定のアルファ値でレンダリングすることにより、青い背景が透けて見えます。3番目のイメージでは、犬の顔の周囲のピクセルは完全に不透明(アルファ=1.0)ですが、顔から離れるに従って、ピクセルのアルファ値は徐々に小さくなっています。
レンダリングのためのGraphics2D
コンテキストを構成するには、Graphics2D
の設定(set)メソッドを使用して、RenderingHints
、Stroke
、Paint
、クリッピング・パスComposite
、Transform
などの属性を指定します。
RenderingHints
オブジェクトは、オブジェクトをレンダリングする方法に関する設定をすべてカプセル化しています。Graphics2D
コンテキストにレンダリング・ヒントを設定するには、RenderingHints
オブジェクトを生成し、Graphics2D.setRenderingHints
にそれを渡します。
レンダリング・モードの変更をサポートしていないプラットフォームもあるので、レンダリング・ヒントを設定しても、特定のレンダリング・アルゴリズムの使用が保証されるわけではありません。
次の例では、アンチエイリアスを有効にし、レンダリングの設定を品質優先にしています。
qualityHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2.setRenderingHints(qualityHints);
BasicStroke
では、Shape
の輪郭線に適用される特性が定義されています。これには、線の幅と破線パターン、線のセグメントの接合方法、および線端に適用される装飾が含まれます。Graphics2D
コンテキストにストローク属性を設定するには、BasicStroke
オブジェクトを生成し、それをsetStroke
メソッドに渡します。
ストロークの幅を設定するには、目的の幅を指定してBasicStroke
オブジェクトを生成し、setStroke
メソッドを呼び出します。
次の例では、ストロークの幅は12ポイントに設定し、接合と線端の装飾にはデフォルトの設定を使用しています。
接合スタイルと線端スタイルを設定するには、目的の属性を指定してBasicStroke
オブジェクトを生成します。
次の例では、ストロークの幅は12ポイントに設定し、接合スタイルと線端スタイルには、デフォルトの設定ではなく、丸みを付けたスタイルを使用しています。
roundStroke = new BasicStroke(4.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); g2.setStroke(roundStroke);
BasicStroke
オブジェクトでは、複雑な破線パターンを簡単に定義できます。そのためには、BasicStroke
オブジェクトを作成するときに、破線パターンを制御する2つのパラメータを指定します。
dash
—破線パターンを表す配列。配列の要素は、交互に、ダッシュ部分のサイズとダッシュ間の空白部分のサイズを表します。要素0は最初のダッシュ部分を示し、要素1は最初の空白部分を示します。dash_phase
—破線パターンの始まる位置を定義するオフセット。次の例では、2種類の破線パターンが線に適用されています。第1のパターンでは、ダッシュのサイズとダッシュ間の空白部のサイズは一定です。第2の破線パターンはさらに複雑で、6つの要素を持つ配列を使用して、破線パターンが定義されています。
float dash1[] = {10.0f}; BasicStroke bs = new BasicStroke(5.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); g2.setStroke(bs); Line2D line = new Line2D.Float(20.0f, 10.0f, 100.0f, 10.0f); g2.draw(line); float[] dash2 = {6.0f, 4.0f, 2.0f, 4.0f, 2.0f, 4.0f}; bs = new BasicStroke(5.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash2, 0.0f); g2.setStroke(bs); g2.draw(line);
どちらの破線パターンも破線のオフセットは0で、破線の描画は破線パターンの先頭から始まっています。この2種類の破線パターンを図2-7に示します。
。
Graphics2D
コンテキストのPaint
属性により、テキストとShape
のレンダリング時に使われる塗りつぶしの色とパターンが決まります。
GradientPaint
クラスは、ある色から別の色へのグラデーションで図形を塗りつぶす簡単な方法を提供しています。GradientPaint
を作成するときに、開始の位置と色および終了の位置と色を指定します。塗りつぶしの色は、2つの位置を結ぶ線に沿って、1つの色から別の色まで、一定の比率で段階的に変化します。図2-8は、グラデーションを使用した塗りつぶしの例です。
図2-8の3番目の星型では、開始位置と終了位置が両方とも図形の内部にあります。グラデーションの向きを示す線をP1より先に延長した部分にある点は、すべて開始位置の色で描画されて、グラデーション線をP2より先に延長した部分にある点は、すべて終了位置の色で描画されます。
ある色から別の色へのグラデーションで図形を塗りつぶすには、次のようにします。
GradientPaint
オブジェクトを作成します。Graphics2D.setPaint
を呼び出します。Shape
を作成します。Graphics2D.fill(shape)
を呼び出します。次の例では、青と緑のグラデーションで矩形を塗りつぶしています。
GradientPaint gp = new GradientPaint(50.0f, 50.0f, Color.blue 50.0f, 250.0f, Color.green); g2.setPaint(gp); g2.fillRect(50, 50, 200, 200);
TexturePaint
クラスでは、繰返しパターンで図形を塗りつぶす簡単な方法が提供されています。TexturePaint
を作成するときは、パターンとして使用するBufferedImage
を指定します。コンストラクタには、パターンの繰返し単位を定義する矩形も渡します。図2-9はこの塗りつぶしの例です。
テクスチャで図形を塗りつぶすには、次のようにします。
TexturePaint
オブジェクトを作成します。Graphics2D.setPaint
を呼び出します。Shape
を作成します。Graphics2D.fill(shape)
を呼び出します。次の例では、バッファリングされたイメージから作成された簡単なテクスチャで矩形を塗りつぶしています。
// Create a buffered image texture patch of size 5x5 BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); Graphics2D big = bi.createGraphics(); // Render into the BufferedImage graphics to create the texture big.setColor(Color.green); big.fillRect(0,0,5,5); big.setColor(Color.lightGray); big.fillOval(0,0,5,5); // Create a texture paint from the buffered image Rectangle r = new Rectangle(0,0,5,5); TexturePaint tp = new TexturePaint(bi,r,TexturePaint.NEAREST_NEIGHBOR); // Add the texture paint to the graphics context. g2.setPaint(tp); // Create and render a rectangle filled with the texture. g2.fillRect(0,0,200,200); }
クリッピング・パスを定義するには、次のようにします。
Shape
を作成します。Graphics2D.setClip
を呼び出して、このShapeをGraphics2D
コンテキストのクリッピング・パスとして使用します。クリッピング・パスを縮小するには、次のようにします。
Shape
を作成します。clip
を呼び出して、現在のクリッピング・パスと新しいShape
の交差部分を新しいクリッピング・パスにします。次の例では、まず楕円形でクリッピング・パスを作成し、次にclip
を呼び出してクリッピング・パスを変更しています。
public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; // The width and height of the canvas int w = getSize().width; int h = getSize().height; // Create an ellipse and use it as the clipping path Ellipse2D e = new Ellipse2D.Float(w/4.0f,h/4.0f, w/2.0f,h/2.0f); g2.setClip(e); // Fill the canvas. Only the area within the clip is rendered g2.setColor(Color.cyan); g2.fillRect(0,0,w,h); // Change the clipping path, setting it to the intersection of // the current clip and a new rectangle. Rectangle r = new Rectangle(w/4+10,h/4+10,w/2-20,h/2-20); g2.clip(r); // Fill the canvas. Only the area within the new clip // is rendered g2.setColor(Color.magenta); g2.fillRect(0,0,w,h); }
Shape
、テキスト文字列またはImage
を変換するには、レンダリングする前に、Graphics2D
コンテキストの変換パイプラインに新しいAffineTransform
を追加します。グラフィック・オブジェクトをレンダリングすると、変換が適用されます。
たとえば、矩形を45度回転させて描画するには、次のようにします。
Graphics2D
変換を取得します。変換をグラフィックス・コンテキストに追加する前に、Graphics2D
に対してgetTransform
を常に呼び出します(グラフィックス・コンテキストが、ウィンドウ内でのSwingコンポーネントや軽量コンポーネントの位置指定など、他の理由で必要な変換を保持している場合があるため)。AffineTransform.getRotateInstance
を呼び出して回転変換を取得します。Graphics2D.transform
を呼び出して、この新しい変換を変換パイプラインに追加します。setTransform
を実行すると、グラフィックス・コンテキスト内の現在の変換が上書きされてしまうため、新しい座標変換を追加するのにsetTransform
を使用しないでください。Rectangle2D.Float
オブジェクトを作成します。Graphics2D.draw
を呼び出して矩形をレンダリングします。setTransform
を呼び出すことにより、Graphics2D
の変換をステップ1で保存した元の変換に戻します。次の例では、矩形をレンダリングするときに、AffineTransform
のインスタンスを使用して矩形を45度回転させています。
AffineTransform aT = g2.getTransform();Rectangle2D rect = new Rectangle2D.Float(1.0,1.0,2.0,3.0); AffineTransform rotate45 = AffineTransform.getRotateInstance(Math.PI/4.0,0.0,0.0) g2.transform(rotate45); g2.draw(rect);g2.setTransform(aT);
次の例では、AffineTransform
を使用して、中心点を軸にテキスト文字列を回転させています。
// Define the rendering transform AffineTransform at = new AffineTransform(); // Apply a translation transform to make room for the // rotated text. at.setToTranslation(400.0, 400.0); g2.transform(at); // Create a rotation transform to rotate the text at.setToRotation(Math.PI / 2.0); // Render four copies of the string “Java” at 90 degree angles for (int i = 0; i < 4; i++) { g2.drawString(“Java”, 0.0f, 0.0f); g2.transform(at); }
イメージも同じ方法で変換できます。レンダリングされるグラフィック・オブジェクトの種類に関係なく、レンダリングの際にはGraphics2D
コンテキストの変換が適用されます。
Graphics2D
コンテキスト内の変換を変更しないで、イメージに変換を適用するには、drawImage
メソッドにAffineTransform
を渡します。
AffineTransform rotate45 = AffineTransform.getRotateInstance(Math.PI/4.0,0.0,0.0) g2.drawImage(myImage, rotate45);
Font
に変換を適用して、見た目の異なるFont
を作成することもできます。詳細については、「フォント派生の作成」を参照してください。
AlphaComposite
は、あるオブジェクトが別のオブジェクトと重なるときの色のレンダリング方法を決める、合成規則をカプセル化しています。Graphics2D
コンテキストに合成スタイルを指定するには、AlphaComposite
を作成し、それをsetComposite
メソッドに渡します。もっとも一般的に使われる合成スタイルはSRC_OVER
です。
SRC_OVER
合成規則は、デスティネーション・ピクセルの上にソース・ピクセルを合成するもので、共有されるピクセルはソース・ピクセルの色になります。たとえば、青い矩形をレンダリングしてから、それと一部が重なる赤い矩形をレンダリングした場合、重なり合う部分の色は赤になります。つまり、最後にレンダリングされたオブジェクトが、いちばん上に表示されます。
SRC_OVER
合成規則を使用するには、次のようにします。
SRC_OVER
規則を指定してgetInstance
メソッドを呼び出すことにより、AlphaComposite
オブジェクトを生成します。AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
setComposite
を呼び出してAlphaComposite
オブジェクトをGraphics2D
コンテキストに追加します。合成オブジェクトがいったん設定されると、重なりを持つオブジェクトは指定されている合成規則を使用してレンダリングされます。
AlphaComposite
を使用すると、アルファ値の定数を追加して指定できます。この値は、ソース・ピクセルのアルファ値に掛けられて、ソース・ピクセルの透明度が高くなります。
たとえば、50%の透明度でソース・オブジェクトをレンダリングするAlphaComposite
オブジェクトを作成するには、アルファ値.5を指定します。
次の例では、ソースを上に重ねるアルファ合成オブジェクトをアルファ値.5で作成し、グラフィックス・コンテキストに追加しています。その結果、それ以降の図形は50%の透明度でレンダリングされます。
public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setColor(Color.red); g2.translate(100,50); // radians=degree * pie / 180 g2.rotate((45*java.lang.Math.PI)/180); g2.fillRect(0,0,100,100); g2.setTransform(new AffineTransform()); // set to identity // Create a new alpha composite AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f); g2.setComposite(ac); g2.setColor(Color.green); g2.fillRect(50,0,100,100); g2.setColor(Color.blue); g2.fillRect(125,75,100,100); g2.setColor(Color.yellow); g2.fillRect(50,125,100,100); g2.setColor(Color.pink); g2.fillRect(-25,75,100,100); }
Graphics2D
では、Shape
、Text
およびImage
のレンダリング用に、次のメソッドが提供されています。
draw
—Graphics2D
コンテキストのStroke
およびPaint
オブジェクトを使用して、Shape
のパスをストロークで描画します。fill
—Graphics2D
コンテキストのPaint
を使用してShape
を塗りつぶします。drawString
—Graphics2D
コンテキストのPaint
を使用して、指定されたテキスト文字列をレンダリングします。drawImage
—指定されたイメージをレンダリングします。図形をストロークで描画して塗りつぶすには、draw
メソッドとfill
メソッドの両方を呼び出す必要があります。
Graphics2D
は、drawOval
やfillRect
など、旧バージョンのJDKで提供されていた描画用と塗りつぶし用のメソッドもサポートしています。
Shape
の輪郭線は、Graphics2D.draw
メソッドでレンダリングできます。旧バージョンのJDKで提供されていた次の描画メソッドもサポートされています。drawLine
、drawRect
、drawRoundRect
、drawOval
、drawArc
、drawPolyline
、drawPolygon
、draw3DRect
。
Shape
を描画すると、Graphics2D
コンテキストのStroke
オブジェクトでパスが描画されます。詳細については、「ストローク属性」を参照してください。Graphics2D
コンテキストに適切なBasicStroke
オブジェクトを設定することで、どのような幅とパターンの線でも描画できます。BasicStroke
オブジェクトでは、線の先端部と接合部の属性も定義されています。
図形の輪郭線を描画するには、次のようにします。
BasicStroke
オブジェクトを作成しますGraphics2D.setStroke
を呼び出しますShape
を作成します。Graphics2D.draw(shape)
を呼び出します。次の例では、GeneralPath
オブジェクトを使用して星型を定義し、BasicStroke
オブジェクトをGraphics2D
コンテキストに追加して、星型の線の幅と接合部の属性を定義しています。
public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; // create and set the stroke g2.setStroke(new BasicStroke(4.0f)); // Create a star using a general path object GeneralPath p = new GeneralPath(GeneralPath.NON_ZERO); p.moveTo(- 100.0f, - 25.0f); p.lineTo(+ 100.0f, - 25.0f); p.lineTo(- 50.0f, + 100.0f); p.lineTo(+ 0.0f, - 100.0f); p.lineTo(+ 50.0f, + 100.0f); p.closePath(); // translate origin towards center of canvas g2.translate(100.0f, 100.0f); // render the star's path g2.draw(p); }
Graphics2D.fill
メソッドを使用して、任意のShape
を塗りつぶすことができます。Shape
を塗りつぶすと、そのパスの内側の領域が、Color
、TexturePaint
、GradientPaint
など、Graphics2D
コンテキストの現在のPaint
属性でレンダリングされます。
旧バージョンのJDKで提供されていた次の塗りつぶしメソッドもサポートされています。fillRect
、fill3DRect
、fillRoundRect
、fillOval
、fillArc
、fillPolygon
、clearRect
。
Shape
を塗りつぶすには、次のようにします。
Graphics2D.setColor
またはGraphics2D.setPaint
を使用して、Shape
を作成します。Graphics2D.fill
を呼び出してShape
をレンダリングします。次の例では、setColor
を呼び出して、Rectangle2D
に緑色での塗りつぶしを定義しています。
public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setPaint(Color.green); Rectangle2D r2 = new Rectangle2D.Float(25,25,150,150); g2.fill(r2); }
テキスト文字列をレンダリングするには、Graphics2D.drawString
を呼び出して、レンダリングする文字列を渡します。テキストのレンダリングとフォントの選択の詳細は、「フォントとテキスト・レイアウト」を参照してください。
Image
をレンダリングするには、Image
を作成し、Graphics2D.drawImage
を呼び出します。イメージの処理とレンダリングの詳細は、「イメージング」を参照してください。
Composite
インタフェースとCompositeContext
インタフェースを実装することで、まったく新しい種類の合成操作を作成できます。Composite
オブジェクトでは、実際に状態を保持して合成の作業を行うCompositeContext
オブジェクトが提供されます。1つのComposite
オブジェクトから複数のCompositeContext
オブジェクトを生成し、マルチスレッド環境の異なる状態を維持できます。
Java 2D APIは、ネイティブ・プラットフォームで構成可能な3つの異なるマルチスクリーン構成をサポートします。
Java 2D APIでは、GraphicsConfiguration
を指定してFrame
、JFrame
、Window
またはJWindow
オブジェクトを作成することにより、レンダリングのターゲットとなる画面デバイスを指定できます。
これら3つの構成で、各画面デバイスはGraphicsDevice
で表されます。GraphicsDevice
は、関連付けられた複数のGraphicsConfiguration
オブジェクトを保持できます。
仮想デバイスの構成に複数の画面が使用される場合、物理画面外に存在する仮想座標系が、仮想デバイスの表現に使用されます。マルチスクリーン構成での各GraphicsConfiguration
の境界は、仮想座標系に対する相対座標になります。この環境下で1つの画面がプライマリ画面として認識され、仮想座標系の(0, 0)に配置されます。図2-10に示すように、プライマリ画面の位置によっては、仮想デバイスが負の座標になる場合があります。
使用している環境が、Window
またはFrame
が複数の物理画面にまたがることのできる仮想デバイス環境であるかどうかを判別するには、システムのGraphicsConfiguration
ごとにgetBounds
を呼び出して、原点が(0, 0)以外に位置しているかどうかを調べます。GraphicsConfiguration
のgetBounds
メソッドは、仮想座標系内のRectangle
を返します。このため、いずれかの原点が(0, 0)以外の場合には、仮想デバイス環境です。
仮想デバイス環境では、GraphicsConfiguration
オブジェクトの座標は仮想座標系に対する相対座標になります。このため、Frame
またはWindow
のsetLocation
メソッドを呼び出す場合には、仮想座標を使用する必要があります。たとえば次のコード例では、GraphicsConfiguration
の境界を取得し、その境界を使用して、対応するGraphicsConfiguration
の物理画面の原点に対し(10, 10)の位置にFrame
を配置します。
Frame f = new Frame(GraphicsConfiguration gc); Rectangle bounds = gc.getBounds(); f.setLocation(10 + bounds.x, 10 + bounds.y);
GraphicsConfiguration
の境界が考慮されない場合、Frame
はプライマリ物理画面の(10, 10)に表示されます。この画面は、指定されたGraphicsConfiguration
の物理画面とは異なる可能性があります。
仮想デバイスの境界判定に、getBounds
メソッドを使用することもできます。システムの各GraphicsConfiguration
に対し、getBounds
を呼び出します。仮想デバイスの境界を判定するには、すべての境界の和集合を計算します。次の例では、その具体的な方法を示します。
Rectangle virtualBounds = new Rectangle(); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice[] gs = ge.getScreenDevices(); for (int j = 0; j < gs.length; j++) { GraphicsDevice gd = gs[j]; GraphicsConfiguration[] gc = gd.getConfigurations(); for (int i = 0; i < gc.length; i++) { virtualBounds = virtualBounds.union(gc[i].getBounds()); } }
次のアプレットは、GraphicsEnvironment
の各GraphicsDevice
の各GraphicsConfiguration
を使用してJFrame
を作成します。各JFrame
は、赤、緑、青のストライプ・セット、画面番号、GraphicsConfiguration
番号およびGraphicsConfiguration
の境界を表示します。
import java.applet.Applet; import java.awt.*; import javax.swing.*; public class MultiFrameApplet extends Applet { public MultiFrameApplet() { main(null); } public static void main(String[] argv) { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice[] gs = ge.getScreenDevices(); for (int j = 0; j < gs.length; j++) { GraphicsDevice gd = gs[j]; GraphicsConfiguration[] gc = gd.getConfigurations(); for (int i=0; i < gc.length; i++) { JFrame f = new JFrame(gs[j].getDefaultConfiguration()); GCCanvas c = new GCCanvas(gc[i]); Rectangle gcBounds = gc[i].getBounds(); int xoffs = gcBounds.x; int yoffs = gcBounds.y; f.getContentPane().add(c); f.setTitle("Screen# "+Integer.toString(j)+", GC# "+Integer.toString(i)); f.setSize(300, 150); f.setLocation((i*50)+xoffs, (i*60)+yoffs); f.show(); } } } } class GCCanvas extends Canvas { GraphicsConfiguration gc; Rectangle bounds; public GCCanvas(GraphicsConfiguration gc) { super(gc); this.gc = gc; bounds = gc.getBounds(); } public Dimension getPreferredSize() { return new Dimension(300, 150); } public void paint(Graphics g) { g.setColor(Color.red); g.fillRect(0, 0, 100, 150); g.setColor(Color.green); g.fillRect(100, 0, 100, 150); g.setColor(Color.blue); g.fillRect(200, 0, 100, 150); g.setColor(Color.black); g.drawString("ScreenSize="+ Integer.toString(bounds.width)+ "X"+ Integer.toString(bounds.height), 10, 15); g.drawString(gc.toString(), 10, 30); } }
目次|前|次 |