自定义 NSScroller 问题

发布于 2024-09-09 06:10:29 字数 1308 浏览 6 评论 0原文

我正在尝试对 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:),但没有成功。还有其他人遇到过类似的问题吗?

I'm trying to subclass NSScroller in order to draw my own scroller knob. To do this, I've subclassex NSScrollView and usex the following code to instantiate my custom 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]];
    }
}

This works and my NSScrollers display correctly. But I'm occasionally seeing rendering issues upon first loading my application. Within Interface Builder I have laid out a number of NSScrollViews with their scrollbars set to hide automatically. The issue I'm seeing is that when the application first loads, the scrollbar backgrounds are rendered across the NSScrollViews contents.

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

I believe this is because I instantiate my NSScroll subclass (TRSubclass) via awakeFromNib, which means that the scrollbars are given the frame of the NSScrollView before it is automatically resized to meet the windows saved location and size (in other words, it's using the frame that's assigned by default within Interface Builder). What's the best way around this?

I've tried forcing the NSScrollView to redisplay (using setNeedsDisplay: and display:) but with no luck. Has anyone else come across a similar issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沫雨熙 2024-09-16 06:10:29

我在我的应用程序中使用相同的模式,并且我经常与这个问题作斗争。我使用相同的技巧:在 [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”检查有助于避免双重交换。

I'm using the same schema in my applications and I fighted this issues a lot. I use the same trick: scrollers are substituted in [scrollView awakeFromNib] methods, but I don't face such rendering issues at the moment. You can try to play with "draws background" property of the NSScrollView - it really helps sometimes

- (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];
}

There are few tricks here, they work depending on a way NSScrollView is created. 'isKindOfClass' check helps to avoid double-swap.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文