首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSOutlineView setNeedsDisplayInRect调用失败

NSOutlineView setNeedsDisplayInRect调用失败
EN

Stack Overflow用户
提问于 2011-06-13 21:04:36
回答 1查看 352关注 0票数 2

我有一个NSOutlineView,它使用自定义的NSCell子类来绘制NSProgressIndicator。每个NSCell都有一个由NSOutlineView委托willDisplayCell:forItem:方法设置的refreshing属性,如下所示:

代码语言:javascript
复制
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
    cell.refreshing = item.refreshing;
}

每个item实例都包含一个NSProgressIndicator,它根据特定项目是否正在刷新而启动和停止。

代码语言:javascript
复制
- (NSProgressIndicator *)startProgressIndicator
{
    if(!self.progressIndicator)
    {
        self.progressIndicator = [[[NSProgressIndicator alloc] initWithFrame:NSMakeRect(0, 0, 16.0f, 16.0f)] autorelease];
        [self.progressIndicator setControlSize:NSSmallControlSize];
        [self.progressIndicator setStyle:NSProgressIndicatorSpinningStyle];
        [self.progressIndicator setDisplayedWhenStopped:YES];
        [self.progressIndicator setUsesThreadedAnimation:YES];
        [self.progressIndicator startAnimation:self];
    }

    return self.progressIndicator;
}
- (void)stopProgressIndicator
{
    if(self.progressIndicator != nil)
    {
        NSInteger row = [sourceList rowForItem:self];

        [self.progressIndicator setDisplayedWhenStopped:NO];
        [self.progressIndicator stopAnimation:self];
        [[self.progressIndicator superview] setNeedsDisplayInRect:[sourceList rectOfRow:row]];
        [self.progressIndicator removeFromSuperviewWithoutNeedingDisplay];

        self.progressIndicator = nil;
    }

    for(ProjectListItem *node in self.children)
    {
        [node stopProgressIndicator];
    }
}   

在我的NSCell的drawInteriorWithFrame:inView:类中停止和启动items NSProgressIndicator实例,如下所示:

代码语言:javascript
复制
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    if(self.refreshing)
    {
        NSProgressIndicator *progressIndicator = [item progressIndicator];
        if (!progressIndicator)
        {
            progressIndicator = [item startProgressIndicator];
        }

        // Set the progress indicators frame here ...

        if ([progressIndicator superview] != controlView)
            [controlView addSubview:progressIndicator];

        if (!NSEqualRects([progressIndicator frame], progressIndicatorFrame)) {
            [progressIndicator setFrame:progressIndicatorFrame];
        }
    }
    else
    {
        [item stopProgressIndicator];
    }

    [super drawInteriorWithFrame:cellFrame inView:controlView];
}

我遇到的问题是,尽管NSProgressIndicators被正确地告知停止,但对stopProgressIndicator的调用没有任何效果。下面的代码未能触发有问题的NSOutlineView行的刷新。我手动检查了调用rectOfRow返回的NSRect,可以确认该值是正确的。

代码语言:javascript
复制
[self.progressIndicator setDisplayedWhenStopped:NO];
[self.progressIndicator stopAnimation:self];
[[self.progressIndicator superview] setNeedsDisplayInRect:[sourceList rectOfRow:row]];
[self.progressIndicator removeFromSuperviewWithoutNeedingDisplay];

self.progressIndicator = nil;

当NSOutlineView完成所有项的刷新时,它会触发一个reloadData:调用。这似乎是唯一可以可靠地更新所有有问题的单元,最终删除NSProgressIndicators的东西。

我在这里做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-06-28 03:51:08

在绘制过程中打乱视图层次结构是一种糟糕的做法。最好的办法是使用NSProgressIndicatorNSCell版本,但是AppKit没有这样的东西。对于类似的问题,在Daniel Jalkut's answer中描述的解决方案可能是您想要的最快的路径。这是基本的想法:

观察项目的refreshing状态,而不是在绘图过程中使用refreshing变量切换路径。当它变为真时,在给定frameOfCellAtColumn:row:的项目位置添加一个NSProgressIndicator作为NSOutlineView的子视图(为最右侧的进度指示器设置一个列可能更方便)。当它变为false时,删除相应的进度指示器。您还需要确保在这些进度指示器上适当地设置自动调整大小标志,以便它们随着大纲视图的大小调整而移动。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6330776

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档