NSScroller 的子类不绘图

Posted

技术标签:

【中文标题】NSScroller 的子类不绘图【英文标题】:Subclass of NSScroller not drawing 【发布时间】:2011-06-20 10:41:03 【问题描述】:

我有一个 NSScrollView,我想知道用户 mouseDown 何时在它的 NSScroller 上。当子类 NSScroller(覆盖 mouseDown)时,我的 NSScrollView 的水平滚动条不再绘制/可见。如果我覆盖了我的 NSScroller 的 drawRect(并使用它的 superview 进行绘图),它会被预期的 NSRect 调用,但没有绘制任何内容。我错过了什么?

实际上,在预期的 HScroller 区域的右侧似乎有一段 15x15 的垂直滚动轨道。也许我需要指定 setFrameRotation 或其他东西......虽然如果我在 MyHScroller 的 drawRect 中调用 NSFillRect,它会绘制预期的矩形 - 如果我旋转 90 度,我的填充在预期的 HScroller 区域的左侧只有 15x15。

这是我的 NSScrollView 创建代码:

MyHScroller  *pMyHScroller  = [[MyHScroller  alloc] init];
MyScrollView *pMyScrollView = [[MyScrollView alloc] initWithFrame:nsrcFrame];
// pMyHScroller = nil;  // With this line uncommented, the HScroller is drawn perfectly
if (pMyHScroller)

    [pMyScrollView setHorizontalScroller:pMyHScroller];

[pMyScrollView setHasVerticalScroller:    NO];
[pMyScrollView setHasHorizontalScroller: YES];
[pMyScrollView setAutohidesScrollers:     NO];
[pMyScrollView setBorderType:  NSBezelBorder];
[pMyScrollView setAutoresizingMask:0|NSViewMinYMargin];

[pMyScrollView setHorizontalLineScroll:  10];
[pMyScrollView setHorizontalPageScroll: 100];
[pMyScrollView setScrollsDynamically:   YES];

这里是 NSScroller 子类:

@interface MyHScroller : NSScroller


- (void)mouseDown:(NSEvent *)eventInfo;
- (void)drawRect:(NSRect)nsrcDirty;
@end 

@implementation MyHScroller // NSScroller
- (void)mouseDown:(NSEvent *)eventInfo

   [super mouseDown:eventInfo];



- (void)drawRect:(NSRect)nsrcDirty

    // This fills the expected HScoller area with yellow
    [[NSColor yellowColor] set];
    NSRectFill(nsrcDirty);

    // This verifies the ends of the rect are visible
    
        [[NSColor cyanColor] set];
        NSBezierPath* aPath = [NSBezierPath bezierPath];
        [aPath moveToPoint:NSMakePoint(bounds.origin.x     , bounds.origin.y                       )];
        [aPath lineToPoint:NSMakePoint(bounds.origin.x+20.0, bounds.origin.y+bounds.size.height/2.0)];
        [aPath lineToPoint:NSMakePoint(bounds.origin.x     , bounds.origin.y+bounds.size.height    )];
        [aPath stroke];
    
    
        [[NSColor cyanColor] set];
        NSBezierPath* aPath = [NSBezierPath bezierPath];
        [aPath moveToPoint:NSMakePoint(bounds.origin.x+bounds.size.width     , bounds.origin.y                       )];
        [aPath lineToPoint:NSMakePoint(bounds.origin.x+bounds.size.width-20.0, bounds.origin.y+bounds.size.height/2.0)];
        [aPath lineToPoint:NSMakePoint(bounds.origin.x+bounds.size.width     , bounds.origin.y+bounds.size.height    )];
        [aPath stroke];
    

    // This draws what appears to be a 15x15 Vertical Scroller track segment
    // over the right size of the yellow rect
    [super drawRect:nsrcDirty];


@end

MyScrollView 只是一个 NSScrollView 覆盖,添加了用于滚动同步的功能。

【问题讨论】:

【参考方案1】:

简单的解决方案...有一个未记录的位标志控制方向和行为:sFlags.isHorz 需要在 NSScroller 子类中设置为 YES 或 NO。

这是一个使用 setFrame 的不必要推荐的示例:覆盖:

-(void)setFrame:(NSRect)nsrcFrame

    [super setFrame:nsrcFrame];
    sFlags.isHoriz = (nsrcFrame.size.width > nsrcFrame.size.height); // otherwise always draws vertically

【讨论】:

...虽然这在 OSX 10.7 (Lion) 中不起作用。在 Lion 中,滚动条是垂直的。

以上是关于NSScroller 的子类不绘图的主要内容,如果未能解决你的问题,请参考以下文章

在 show() 之前获取 DialogFragment 子类中的父活动

自定义 NSScroller 问题

如何在 Lion 中自动隐藏 NSScroller?

为啥要使用 DialogFragment?

在 NSScrollView 问题中绘制自定义 NSScroller

带有 Core Graphics 绘图的 Core Animation