|
|
Log In | Not a Member? |
Contact ADC |
| < Previous PageNext Page > |
アプリケーションは、内容を表示したりユーザの操作に応答したりするために、ウインドウを使用して画面の領域を確保します。ウインドウは、描画処理とイベント処理の両方において必要不可欠なものです。
アプリケーションのウインドウ
NSWindowとウインドウサーバ
ウインドウのバッファ処理
ウインドウのZ軸順とレベル
ウインドウの部品
ウインドウの座標
ウインドウと描画
ウインドウのステータス
ウインドウとイベント処理
パネル
表示されるウインドウを持たないアプリケーション(バックグラウンドアプリケーションなど)も可能ですが、そのようなアプリケーションはまれです。一般に、アプリケーションには、表示できるウインドウの数に基づいて、以下の2種類が存在します。
ドキュメントベース―複数のドキュメントを個別のウインドウに作成することのできるアプリケーション。たとえば、ワードプロセッサアプリケーションや描画アプリケーションなどがあります。ドキュメントベースアプリケーションでは、ユーザはメニューオプション(通常は「ファイル」>「新規」)を選んで新しいドキュメントを作成します。Cocoaのほとんどのドキュメントベースアプリケーションは、Cocoaのドキュメントアーキテクチャがベースとなっています(このアーキテクチャの概要については、“「Cocoaのその他のアーキテクチャ」”を参照してください)。
単一ウインドウ―常に1つのウインドウのみを表示するアプリケーション。たとえば、Mac OS XではiSyncやFont Bookなどがあります。単一ウインドウアプリケーションを起動すると、そのウインドウが表示されます。多くの場合、そのウインドウを閉じるとアプリケーションが終了します。
また、どのようなアプリケーションでも、ダイアログやパネルと呼ばれる二次ウインドウを持つことができます。これらの二次ウインドウは、現在のドキュメントウインドウに従属するか、または単一ウインドウアプリケーションの場合はメインウインドウに従属します。二次ウインドウはさまざまな手段によってドキュメントウインドウやメインウインドウを支援します。たとえば、フォントや色を選択できるようにしたり、パレットからツールを選択できるようにしたり、警告を表示したりします。多くの場合、二次ウインドウはモーダルです。詳細については、“「パネル」”を参照してください。
Cocoaでは、NSWindowオブジェクトが物理ウインドウを表します。ウインドウサーバは物理ウインドウを作成し、最終的にそれらを画面上で管理します。ウインドウサーバは、識別子となる一意の番号を各ウインドウに割り当てます。NSWindowオブジェクトとその物理ウインドウとのつながりは、このウインドウ番号を通じて確立されます。
ウインドウサーバはウインドウを作成するときに、ウインドウグラフィックスコンテキストを取得し、グラフィック状態スタックを初期化します。また、ウインドウサーバはウインドウのバッキングストアも作成します。バッキングストアとは、ディスプレイデバイスのフレームバッファに配置するウインドウのピクセル値を格納するメモリ領域のことです。
注: バッキングストアを持たないウインドウを作成することも可能です。このようなウインドウのことを遅延ウインドウと呼びます。遅延ウインドウのバッキングストアは、ウインドウのZ軸順が画面上で変更されるときに作成されます。
画面上にウインドウが複数ある場合、それらが重なり合うことが多くあります。複数のウインドウが互いに重なり合っているときに、部分的に見えなくなっているウインドウの上でマウスをクリックすると、通常はそのウインドウが前面に移動します。その結果、見えなくなっていた内容が表示されます。ウインドウが表示バッファを持っている場合は、ウインドウサーバによってそのウインドウの内容が自動的に表示されます。ウインドウが表示バッファを持っていない場合は、アプリケーションの側で再描画する必要があります。
ウインドウのバッファ処理には2つの種類があります。ウインドウの表示バッファには、ウインドウ全体のピクセル値か、ウインドウの現在見えなくなっている部分のピクセル値が格納されます。表示バッファを持っている隠れたウインドウが最前面に表示されるときは、ウインドウサーバによって、表示すべき領域が表示バッファから画面にコピーされます。NSWindowオブジェクトを作成するときは、Figure 6-5に示す3つのバッファ処理方式のうちの1つを指定できます。
非保持。表示バッファが提供されません。描画はすべて画面上で直接行われます。つまり、ピクセル値がフレームバッファに直接書き込まれます。ウインドウの一部が別のウインドウに覆われた場合は、そのウインドウ部分のコンテンツ領域のビット情報が失われます。隠れていたウインドウが表示されるときは、隠れていた部分はアプリケーションが再描画する必要があります。アプリケーションで描画を行わない場合、その部分はウインドウの背景色で表示されます。
保持。保持ウインドウは表示バッファを持ちますが、描画は可能な限り画面に直接行われます。表示バッファは、ウインドウに見えなくなる部分が生じるまで変化しません。見えなくなった部分が生じると、その領域のピクセル値が表示バッファに書き込まれます。見えなくなっていた領域が後で表示されるときは、表示バッファの内容が画面にコピーされます。
バッファ。バッファには、バッキングストアにあるものとまったく同じ複製が格納されます。実際、描画は表示バッファに対して実行され、次にその内容が画面にフラッシュされます。影がある場合や透明度が関係する場合は、重なり合っているウインドウと合成されます。ウインドウ全体が隠されて後にそのウインドウが最前面に表示された場合は、表示バッファ全体が画面にコピーされます。
透明効果や非矩形の形状では、バッファ方式のウインドウが必要になるため、Cocoaのウインドウはそのほとんどすべてがバッファ方式です。非保持方式のウインドウは一時的な画像や単純な接続線分に適しています。たとえば、Interface Builderでターゲット/アクションの接続に使用されます。
ウインドウサーバは、画面上に表示するウインドウを、前面から背面へと向かう順序で維持しています。この順序のことを、スクリーンリスト、またはZ軸順と呼びます。ウインドウはそれぞれリストの中で一意の位置を占めています。リストの一番最初のウインドウは、最前面ウインドウです。リストの一番最後のウインドウは、ほかのすべてのウインドウが手前に重なっている可能性があります。それ以外の位置にあるウインドウは、ほかのウインドウよりも手前または奥に位置します。ユーザがウインドウをクリックすると、そのたびにZ軸順が変わり、クリックされたウインドウが最前面になり、以前に最前面だったウインドウがその奥に移動します。
ウインドウの重なりの概念はウインドウレベルによってさらに複雑になります。ウインドウレベルとは、特定の機能を持つウインドウ群が重なり構造として集まったものです。ウインドウレベルは階層的な順序であり、レベルが高いほうのウインドウがレベルが低いほうのウインドウの手前に表示されます。この仕組みによって、ある特定の種類のウインドウが、別のレベルのウインドウよりも常に手前または奥に表示されることが保証されます。たとえば、モーダルシステムダイアログは、必ずすべてのアプリケーションウインドウの手前に表示されます。このように、Z軸順は、実際にはウインドウレベルの中で維持されます(Figure 6-6を参照)。
ウインドウサーバは、以下の順序で、複数のウインドウレベルをサポートしています。
スクリーンセーバ(スクリーンセーバは、自身の内容を表示するために画面サイズのウインドウを使用しますが、タイトルバーはありません)。スクリーンセーバウインドウはほかのすべてのウインドウの手前に表示されます。
メニューバー(アプリケーションメニューを含む)。
Dock。
モーダルウインドウとパネル(“「モーダルウインドウ」”を参照)。
コンテキストメニュー。
フローティングウインドウ(描画アプリケーションのパレットウインドウなど)。
上記以外の種類のウインドウ(アプリケーションウインドウを含む)。
ウインドウはスクリーンリストから明示的に除外することができます。この場合、除外したウインドウのことをオフスクリーンウインドウと呼びます。ウインドウは、リストから削除すると表示が消え、リストに戻すると再び画面に表示されます。オフスクリーンウインドウにはイベントはディスパッチされません。ウインドウをスクリーンリストから除外することが、ウインドウを非表示にするアプリケーションの機能の基本になります。オフスクリーンウインドウは、そのウインドウへの描画が行えるように、バッファ方式か保持方式にする必要があります。
注: 境界線のないウインドウの場合は、そのフレーム座標を画面の可視座標の範囲外に設定することで、画面から消すこともできます。ただし、それ以外のウインドウではこの方法は実行できません。境界線付きのウインドウについては、少なくともその一部分が画面の境界内に表示され続けるように、Application Kitによって制限が課せられます。
NSWindowでは、アプリケーションウインドウのZ軸順を操作するメソッド、スクリーンリストに対してウインドウの追加や除外を行うメソッド、および、ウインドウのレベルを設定するメソッドが、それぞれ定義されています。詳細については、NSWindowクラスのリファレンスを参照してください。
ウインドウには、フレーム領域とコンテンツ領域という、2つの主要な部品があります(Figure 6-7を参照)。これらの領域はビューであり、具体的にはNSViewのサブクラスのインスタンスです(“「ビュー」”を参照)。フレームビューはウインドウ領域全体を囲むもので、ウインドウの境界線とタイトルバーを描画します。フレームビューはNSWindowによって作成されるプライベートオブジェクトです。公開されておらず、サブクラス化による変更は想定されていません。ただし、ウインドウを作成するときに、フレームビューに持たせるコントロールその他の機能(「閉じる」ボタン、最小化ボタン、サイズ変更の三角形、タイトルなど)を指定することができます。
コンテンツビューはフレームビューの中にはめ込まれるもので、通常はタイトルバーとウインドウ境界線を除く領域全体を占めます。Figure 6-7ではフレームビューを基準としてコンテンツビューを示しています(タイトルバーや可視の境界線を持たないウインドウを作成することもできますが、そのようなウインドウにもフレームビューは存在します)。コンテンツビューは、フレームビューの唯一のパブリックサブビューです。プライベートビューではないため、必要ならば独自にカスタムビューに置き換えることもできます。コンテンツビューはスーパービュー(つまり、ビュー階層の中でコンテンツビューを所有し、コンテンツビューを囲うビュー)を持っていますが、そのスーパービューはプライベートオブジェクトです。したがって、コンテンツビューはウインドウのビュー階層のルートになります。ビュー階層の詳細については、“「ビュー」”を参照してください。
すべてのビューオブジェクトと同様に、コンテンツビューでも自身のウインドウへの参照を維持しており、windowメソッドを通じてアクセスできます。Figure 6-8に、NSAppとそのウインドウリスト、リスト内の各ウインドウのコンテンツビュー、およびそれらのオブジェクト間の関係を示します。
ウインドウの座標は画面の座標が基準になります。画面全体を2次元座標格子の第一象限と捉え、左下隅を原点とし、x軸の正を右の水平方向、y軸の正を上の垂直方向に、それぞれとることができます(Figure 6-9を参照)。画面内の座標点は、この座標格子を基準とすることによって特定できます。
画面座標系の主な機能は、画面上でのウインドウの位置を設定することです。アプリケーションで新しいウインドウを作成して画面上に配置するときは、ウインドウの初期のサイズと位置を画面座標で指定する必要があります。ただし、ウインドウの中で描画を行う場合は、そのウインドウに固有の別の座標系である基本座標系(Figure 6-10を参照)を使用します。この座標系は以下の2つの点で画面座標系と異なります。
特定のウインドウにのみ適用される。ウインドウはそれぞれ独自の基本座標系を持つ。
原点は、画面の左下隅ではなくウインドウの左下隅になる。ウインドウが移動すると、原点と座標系全体も一緒に移動する。ウインドウがどの位置にあっても、画像は基本座標系内の位置を保つ。
基本座標系は、ウインドウのビューの個々の座標系を定義するための基準点になります。フレームビューでは、ウインドウの境界線とタイトルバーが直接、基本座標系で描画されます。コンテンツビューとそのサブビューでは、基本座標系を座標変換した座標系で描画が行われます。
ウインドウは自身を描画することはありません。ウインドウ描画の処理はウインドウに含まれているビューに任されます。ただし、NSWindowオブジェクトは自身のビューの描画を調整するうえで重要な役割を果たします。
通常は、イベントループの1回の過程(パス)の中で、アプリケーション内のオブジェクトによってビュー(またはビューのリージョン)が要再描画としてマークされる可能性があります。NSWindowオブジェクトは、それらの「ダーティ」ビューへの参照をリストに収集します。ビューの順序はビュー階層内の位置によって決まります。その後すぐに(通常はイベントサイクルの最後で)、Application Kitは一番上のビュー(つまり、コンテンツビューに最も近いビュー)を起点に、このリストの反復処理を行い、各ビューに対してビュー自身の描画を要求します。このようにして、ほかのビューの背景にあるビューから先に描画されます。
上記に示したウインドウのビューの自動描画は、ウインドウの自動表示機能がオンになっている場合にのみ実行されます。この機能はデフォルトでオンになっています(setAutodisplay:メソッドを参照)。この機能をオフにした場合は、アプリケーションで必要に応じてウインドウのコンテンツを更新する必要があります。あるいは、display、displayRect:、またはdisplayRectIgnoringOpacity:メッセージを任意のNSViewオブジェクトに送信して、自動表示のメカニズムをバイパスすることもできます。バイパスの結果、ビューとそのサブビューは直ちに再描画されます。詳細については、“「ビューの表示」”を参照してください。
NSWindowのdisplayおよびdisplayIfNeededメソッドを使用すると、ウインドウ全体を再描画できます。これらのメソッドではウインドウのビューが直ちに強制的に表示されますが、後者のメソッドは無効化されたビューのリストについてのみ反復処理を行います。displayメソッドを実行すると、ウインドウのビュー階層内の各ビューが、コンテンツビューを起点に、自分自身の再描画を行います。このメソッドは、単発のウインドウ(つまり、ウインドウがオフスクリーンのときにそのバッキングストアが解放されるウインドウ)が画面上に表示される前に、そのウインドウを対象に呼び出されます。また、setFrame:display:の第2引数にYESを指定して呼び出すことで、ウインドウのサイズを変更し、そのすべてのビューを再描画するようにできます。
ウインドウの表示に関連するメカニズムとして、ウインドウの更新があります。イベントループを通過するたびに、NSAppから、そのウインドウリスト内の各ウインドウに、updateメッセージが送信されます。updateのデフォルト実装は何も実行しませんが、NSWindowのサブクラスでこのメソッドをオーバーライドし、アプリケーションの状態を調べ、必要に応じてウインドウの動作や外観を変更することができます。
アプリケーションの各ウインドウには、ユーザによるウインドウとのやり取りに関連するステータスがあります。このステータスはウインドウの外観によって示されます。非アクティブのウインドウは、開いており、表示されている場合がありますが、前面にはありません。非アクティブウインドウのタイトルバーにあるコントロールやタイトルは、グレイ表示されます。ユーザは非アクティブウインドウをクリックして前面に移動しない限り、それらのウインドウとやり取りすることはできません。
アクティブのウインドウは、現在ユーザの入力や注意の焦点となっているウインドウです。アクティブウインドウは前面にあり、それらのコントロールには色が付き、タイトルは黒のフォントで表示されます。アクティブウインドウは、メインおよびキーという2つのステータスを持つことができます。現在ユーザの注意の焦点となっているアクティブウインドウが、メインウインドウです。メインウインドウはほとんどの場合キーウインドウでもあります。現在キーボードイベントを受け付けているウインドウが、キーウインドウです。
しかし、メインウインドウとキーウインドウが別々のウインドウであることもあります。メインウインドウが依然としてユーザの注意の焦点ではありますが、キーイベントの入力フォーカスは別のウインドウになります。キーウインドウには、ユーザがキーボードで文字を入力できるテキストフィールドなどのオブジェクトを持たせる必要があります。この場合、キーウインドウは通常、ユーザがメインウインドウに関係するデータを指定するダイアログまたはパネルです(「検索」ダイアログなど)。
アプリケーションオブジェクト(NSApp)では、アプリケーションの各ウインドウのメインステータスとキーステータスが維持されます。多くの場合、ウインドウのステータスによって、ウインドウが受信およびディスパッチするイベントが決まります( “「イベントのディスパッチについて」”を参照)。
NSWindowは、主に2つの方法でイベントおよびイベント処理に関与します。その1つはイベントのディスパッチで、積極的に関与します。もう1つは、制約されたイベントストリームを受動的に受信することです。
“「イベントのディスパッチについて」”で説明したように、アプリケーションは、イベントが「属する」NSWindowオブジェクトにsendEvent:を送信することによって、受信したイベントのほとんどをディスパッチします。イベントを受信したウインドウオブジェクトは、イベントを受信する必要のあるNSViewオブジェクトを特定し、該当するNSResponderメッセージをそのビューに送信して、NSEventオブジェクトを渡します。たとえば、イベントがキー押下イベントであればkeyDown:をビューに送信し、イベントがマウスドラッグイベント(左ボタン)であればmouseDragged:イベントを送信します。通常、ウインドウオブジェクトがターゲットとなるビューを特定する方法は、キーイベントの場合とマウスイベントの場合とで異なります。
キー押下イベント(NSKeyDown)とマウス左ボタン押下イベント(NSLeftMouseDown)では、最も多くの処理が必要になります。NSWindowは、最初のレスポンダビューへのkeyDown:メッセージの送信を試みる前に、1つ(または複数)のキー文字をシステムの入力マネージャに供給します。入力マネージャは、受け取った入力を、挿入するテキストまたは実行するコマンドとして解釈します。また、mouseDown:メッセージを送信する前に、NSWindowはターゲットのビューをFirst Responderにすることを試みます。特定の修飾子キーが押されている場合は、メッセージをまったく送信せず、代わりにコンテキストヘルプやコンテキストメニューを表示することによってメッセージを処理します。
通常、アプリケーションは、主にユーザの操作が発生した場所に基づいて、イベントをすべてのウインドウに分配します。しかし、場合によっては、アプリケーションによってウインドウがモーダルに実行され、ウインドウを閉じる前にアプリケーションでユーザが何らかの作業(ファイルの選択、名前の入力、あるいは「OK」ボタンのクリックなど)を完了するように求められる場合があります。モーダルウインドウはMac OS Xではよく見ます。たとえば、エラーメッセージダイアログや書類を開いたりプリントしたりするためのパネルがあります。
NSWindowオブジェクトは、モーダルウインドウのメカニズムにおいて受動的な参加者になっており、アプリケーションが、モーダルの動作をプログラムから開始したり管理したりする役割を担っています。ウインドウをモーダルに実行する場合、NSAppでは通常のイベントループの仕組みが使用されますが、入力は特定のウインドウやパネルに限定されます。ループの中ではイベントがフェッチされますが、イベントが特定の条件(最も重要なのはモーダルウインドウとの関連性)を満たさない場合、それらのイベントは破棄されます。
NSApplicationではウインドウをモーダルに実行するための手段がいくつか用意されています。
ブロック―ユーザがモーダルウインドウを閉じるまで、アプリケーションがブロックされます。
非ブロック(モーダルセッション)―アプリケーションがモーダルセッションを開始し、イベントループの1回のパスの間、ウインドウをモーダルに実行します。モーダルセッションのコードは、何らかの条件が満たされるまで、ループの中でウインドウのモーダル実行を続けることができます。
Application Kitのほかのクラスでも、ウインドウやパネルをモーダルに実行するためのメソッドが用意されています。
パネルは、アプリケーションやドキュメントウインドウを支援する役割を担う二次ウインドウです。しばしば、パネルはダイアログと呼ばれます。Cocoaでは、パネルはNSPanelのインスタンスか、NSPanelのサブクラスです。パネルは、その補助的な機能に適した特別な動作を備えています。パネルはキーウインドウになれますが、メインウインドウにはなれません。デフォルトでは、パネルはアプリケーションが非アクティブになったときに画面から消え、アプリケーションが再びアクティブになったときに再表示されます(ただし警告ダイアログはこの動作の例外です)。パネルは反復的な使用を目的としているため、閉じられたときに解放されません。パネルはまた、ユーティリティウインドウなどのフローティングウインドウになるように設定することも可能です。フローティングウインドウは、アプリケーションのほかのウインドウよりも上のレベルにあります。
| < Previous PageNext Page > |
Last updated: 2006-05-23
|
Get information on Apple products.
Visit the Apple Store online or at retail locations. 1-800-MY-APPLE Copyright © 2007 Apple Inc. All rights reserved. | Terms of use | Privacy Notice |