在Scroll上重绘NSCollectionView会导致图形分解

时间:2009-11-18 19:51:12

标签: objective-c xcode drawrect nscollectionview nscollectionviewitem

我在NSCollectionView中有轻微刺激,当我滚动窗口时,NSCollectionViewItem会在视觉上分解。

分手率取决于滚动率。例如,如果我慢慢滚动,分解会更频繁地发生。快速滚动不那么容易。看来问题是当我使用的NSCollectionViewItem的自定义NSView跨越可视框架的边界时。

我的NSView(NSCollectionViewItem的自定义视图)有一个非常简单的绘图算法 - 没有太复杂。

基本上我在drawRect方法的dirtyRect中创建一个框架,并在其中创建一些框架:

-(void)drawRect:(NSRect)dirtyRect
{   
    NSRect mOuterFrame = NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, 104, 94);
    NSRect mSelectedFrame = NSInsetRect(mOuterFrame, 2, 2);
    NSRect mRedFrame = NSInsetRect(mSelectedFrame, 2, 2);
    NSRect mInnerFrame = NSInsetRect(mRedFrame, 2, 2);

    NSBezierPath * mOuterFramePath = [NSBezierPath bezierPathWithRect:mOuterFrame];
    NSBezierPath * mSelectedFramePath = [NSBezierPath bezierPathWithRect:mSelectedFrame];
    NSBezierPath * mRedFramePath = [NSBezierPath bezierPathWithRect:mRedFrame];
    NSBezierPath * mInnerFramePath = [NSBezierPath bezierPathWithRect:mInnerFrame];

    [mainBackgroundColor set];
    [mOuterFramePath fill];

    if (selected)
        [[NSColor yellowColor] set];
    else
        [mainBackgroundColor set];

    [mSelectedFramePath fill];

    if (isRedBorder)
        [[NSColor redColor] set];
    else
        [mainBackgroundColor set];

    [mRedFramePath fill];

    [[NSColor blackColor] set];
    [mInnerFramePath fill];
}

我已尝试锁定焦点并在代码之前和之后释放以及设置图形上下文并恢复它 - 这些似乎都无法解决问题。

我正在使用Snow Leopard - 而不是我认为这会产生影响。

解决方案更新

对于任何感兴趣的人都是NSResponder推荐的问题解决方案。我正在根据mOuterFrame方法drawRect:创建初始dirtyRect,正如所指出的那样,这是不正确的事情。快速更改:

NSRect mOuterFrame = NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, 104, 94);

基于0的起点:

NSRect mOuterFrame = NSMakeRect(0, 0, 104, 94);

我还调整了代码的效率,就像我只使用矩形一样,尽管上面的代码更改足以解决问题本身。我不得不添加一个更改来获得两个像素的行。新方法:

-(void)drawRect:(NSRect)dirtyRect
{   
    NSRect mOuterFrame = NSMakeRect(0, 0, 104, 94);
    NSRect mSelectedFrame = NSInsetRect(mOuterFrame, 2, 2);
    NSRect mRedFrame = NSInsetRect(mSelectedFrame, 2, 2);
    NSRect mInnerFrame = NSInsetRect(mRedFrame, 2, 2);

    [NSBezierPath setDefaultLineWidth:2.0];

    [mainBackgroundColor set];
    [NSBezierPath strokeRect:mOuterFrame];

    if (selected)
        [[NSColor yellowColor] set];
    else
        [mainBackgroundColor set];

    [NSBezierPath strokeRect:mSelectedFrame];

    if (isRedBorder)
        [[NSColor redColor] set];
    else
        [mainBackgroundColor set];

    [NSBezierPath strokeRect:mRedFrame];

    [[NSColor blackColor] set];
    [NSBezierPath strokeRect:mInnerFrame];
}

1 个答案:

答案 0 :(得分:1)

我注意到的第一件事是上面的代码相当浪费,因为当你可以使用NSFrameRect()和NSRectFill()时,你创建了一堆路径。

其次,绘制的几何图形不应该依赖于传递给-drawRect:的矩形。该矩形只是告诉您要更新的区域是什么,因此如果您的视图很复杂,您可以更有效地决定要绘制的内容。