【问题标题】:Redrawing NSCollectionView on Scroll Causes Breakup of Graphics在 Scroll 上重绘 NSCollectionView 会导致图形中断
【发布时间】:2009-11-18 19:51:11
【问题描述】:

我对@9​​87654321@ 有一点刺激,当我滚动窗口时,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 推荐的问题的解决方案。我正在根据drawRect: 方法dirtyRect 创建初始mOuterFrame,正如所指出的那样,这是不正确的做法。快速更改:

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

【问题讨论】:

    标签: objective-c xcode drawrect nscollectionview nscollectionviewitem


    【解决方案1】:

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

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

    【讨论】:

    • 我认为你的意思是 NSFrameRect 不是 NSDrawRect
    • NSResponder - 谢谢。这解决了这个问题(不是基于dirtyRect的初始外框)。我还调整了代码以更有效地使用 NSFrameRect。谢谢!
    猜你喜欢
    • 2017-05-18
    • 2015-10-13
    • 2016-07-27
    • 2018-11-19
    • 2012-11-08
    • 1970-01-01
    • 2018-10-01
    • 2013-06-02
    • 2012-05-06
    相关资源
    最近更新 更多