Q:NSOpenGLView サブクラスのあるインスタンスが、そのウインドウを一度閉じて再び開くと、正しく描画されません。何が起きているのでしょうか。どうすれば修正できるでしょうか。
A:Mac OS X v10.3 以前では、ウインドウを閉じて再び開くと、NSOpenGLView が適切に再描画されません。1 つの簡単な対応策は、階層からビューを削除して、再度挿入することです。
以下のコードでは、ウインドウが閉じられるという通知を受け取るために MyOpenGLView が自身を登録します。-prepareForWindowClosing: メソッドでは、ビューはウインドウが再び開かれるときに送信される NSWindowDidUpdateNotification を受け取るためにも自身を登録します。
-windowReopened: メソッドはビューを保存し、ビュー階層からビューを削除し、再びビューを挿入し、-retain メッセージと -release メッセージの釣り合いを保ちます。
リスト 1:NSOpenGLView の描画環境のリセット
@implementation MyOpenGLView
- (void) awakeFromNib
{
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(prepareForWindowClosing:)
name: NSWindowWillCloseNotification
object: [self window]];
}
- (void) prepareForWindowClosing:(NSNotification *) notification
{
// 次にウインドウが更新されるタイミングを知る必要がある。
//それは、ウインドウが再度開かれるとき。
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(windowReopened:)
name: NSWindowDidUpdateNotification
object: [self window]];
// ウインドウが再び開かれたら、すぐに描画すること。
[self setNeedsDisplay:YES];
}
- (void) windowReopened:(NSNotification *)aNotification
{
// NSOpenGLView の状態を修正するには、ビュー階層からビューを削除して
// 再度追加する
NSView *superviewStash = [self superview];
[self retain]; // スーパービューから削除する前に、保存する必要がある
[self removeFromSuperview];
[superviewStash addSubview:self];
[self release]; // すべての -retain および -release メッセージの釣り合いを保つ必要がある。
// 以降は、ウインドウ露出通知を気にする必要はないため、
// それらの通知の受け取りを停止する
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:NSWindowDidUpdateNotification
object:[self window]];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
@end
ドキュメントの改訂履歴
掲載日: 2004-12-03 |