高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technical Q&A QA1353
NSOpenGLView redraw problems after a window is closed and re-opened.

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 初版

掲載日: 2004-12-03