自定义NSScroller问题

时间:2010-07-15 13:46:14

标签: cocoa macos nsscrollview nsscroller

我正在尝试子类化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中,我已经布置了许多NSScrollViews,其滚动条设置为自动隐藏。我看到的问题是,当应用程序首次加载时,滚动条背景将跨NSScrollViews内容呈现。

alt text http://www.freeimagehosting.net/uploads/1d3fc75db8.png

我相信这是因为我通过awakeFromNib实例化我的NSScroll子类(TRSubclass),这意味着在自动调整大小以满足窗口保存的位置和大小之前,滚动条被赋予NSScrollView的框架(换句话说,它是使用Interface Builder中默认分配的框架。最好的方法是什么?

我已经尝试强制NSScrollView重新显示(使用setNeedsDisplay:并显示:)但没有运气。还有其他人遇到过类似的问题吗?

1 个答案:

答案 0 :(得分: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'检查有助于避免双重交换。