自定义 NSScroller 问题

Posted

技术标签:

【中文标题】自定义 NSScroller 问题【英文标题】:Custom NSScroller issues 【发布时间】:2010-07-15 13:46:13 【问题描述】:

我正在尝试继承 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 内容中呈现。

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

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

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

【问题讨论】:

【参考方案1】:

我在我的应用程序中使用相同的架构,并且我经常解决这个问题。我使用相同的技巧:滚动条被[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' 检查有助于避免双重交换。

【讨论】:

不幸的是,在我的 NSScrollViews 上关闭“绘制背景”没有任何效果。无论如何,我都会有兴趣查看您的代码。 我已经编辑了我的帖子,请检查代码。至于“绘制背景”选项 - 它应该被打开。设置什么背景颜色也很重要,您是否更改了滚动视图中的 NSClipView 实例(实际上是呈现背景的剪辑视图)等。

以上是关于自定义 NSScroller 问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Lion 中自动隐藏 NSScroller?

NSScroller 的子类不绘图

如何绘制一个透明的 NSScroller

wpf 自定义控件的自定义属性的数据绑定问题

在自定义单元格中设置自定义附件类型

自定义控件添加自定义属性问题