2

独自のスクローラー ノブを描画するために、NSScroller をサブクラス化しようとしています。これを行うには、NSScrollView をサブクラス化し、次のコードを使用してカスタム NSScrollers をインスタンス化します。

- (void)awakeFromNib;
{
    NSRect horizontalScrollerFrame = [[self horizontalScroller] frame];
    NSRect verticalScrollerFrame = [[self verticalScroller] frame];
    NSString *scrollBarVariant = [[[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain] valueForKey:@"AppleScrollBarVariant"];

    if (![scrollBarVariant isEqualToString:@"DoubleBoth"]) {
        [self setVerticalScroller:[[[TRScroller alloc] initWithFrame:verticalScrollerFrame] autorelease]];
        [self setHorizontalScroller:[[[TRScroller alloc] initWithFrame:horizontalScrollerFrame] autorelease]];
    }
}

これは機能し、私の NSScrollers は正しく表示されます。しかし、アプリケーションを最初にロードする際にレンダリングの問題が発生することがあります。Interface Builder 内で、スクロールバーが自動的に非表示になるように設定された多数の NSScrollView をレイアウトしました。私が見ている問題は、アプリケーションが最初に読み込まれるときに、スクロールバーの背景が NSScrollViews コンテンツ全体にレンダリングされることです。

代替テキスト http://www.freeimagehosting.net/uploads/1d3fc75db8.png

これは、awakeFromNib を介して NSScroll サブクラス (TRSubclass) をインスタンス化するためだと思います。つまり、スクロールバーには、ウィンドウの保存場所とサイズに合わせて自動的にサイズ変更される前に、NSScrollView のフレームが与えられます (つまり、フレームを使用しています)。 Interface Builder 内でデフォルトで割り当てられます)。これを回避する最善の方法は何ですか?

NSScrollView を (setNeedsDisplay: と display: を使用して) 強制的に再表示しようとしましたが、うまくいきませんでした。他の誰かが同様の問題に遭遇しましたか?

4

1 に答える 1

2

私は自分のアプリケーションで同じスキーマを使用しており、この問題と何度も戦いました。私は同じトリックを使用します: スクローラーは[scrollView awakeFromNib]メソッドで置き換えられますが、現時点ではそのようなレンダリングの問題に直面していません. の「背景を描画する」プロパティを試してみることができますNSScrollView-時々本当に役立ちます

- (void)changeSubs
{
    // change clip view
    // ...

    // change scrollers
    NSRect horizontalScrollerFrame = [[self horizontalScroller] frame];
    NSRect verticalScrollerFrame = [[self verticalScroller] frame];
    if (![[self verticalScroller] isKindOfClass:[CRScroller class]])
        [self setVerticalScroller:[[[CRScroller alloc] initWithFrame:verticalScrollerFrame] autorelease]];
    if (![[self horizontalScroller] isKindOfClass:[CRScroller class]])
        [self setHorizontalScroller:[[[CRScroller alloc] initWithFrame:horizontalScrollerFrame] autorelease]];
}

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
    [self changeSubs];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    NSKeyedUnarchiver* unpacker = (id)aDecoder;
    [unpacker setClass:[CRClipView class] forClassName:[NSClipView className]];
    [unpacker setClass:[CRScroller class] forClassName:[NSScroller className]];

    self = [super initWithCoder:aDecoder];
    if (self)
    {
    }
    return self;
}

- (void)awakeFromNib
{
    [self changeSubs];
}

ここにはいくつかのトリックがあり、NSScrollView の作成方法に応じて機能します。「isKindOfClass」チェックは、二重スワップを回避するのに役立ちます。

于 2010-07-15T14:24:21.397 に答える