我有一个NSOutlineView,它使用自定义的NSCell子类来绘制NSProgressIndicator。每个NSCell都有一个由NSOutlineView委托willDisplayCell:forItem:方法设置的refreshing属性,如下所示:
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
cell.refreshing = item.refreshing;
}每个item实例都包含一个NSProgressIndicator,它根据特定项目是否正在刷新而启动和停止。
- (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实例,如下所示:
- (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,可以确认该值是正确的。
[self.progressIndicator setDisplayedWhenStopped:NO];
[self.progressIndicator stopAnimation:self];
[[self.progressIndicator superview] setNeedsDisplayInRect:[sourceList rectOfRow:row]];
[self.progressIndicator removeFromSuperviewWithoutNeedingDisplay];
self.progressIndicator = nil;当NSOutlineView完成所有项的刷新时,它会触发一个reloadData:调用。这似乎是唯一可以可靠地更新所有有问题的单元,最终删除NSProgressIndicators的东西。
我在这里做错了什么?
发布于 2011-06-28 03:51:08
在绘制过程中打乱视图层次结构是一种糟糕的做法。最好的办法是使用NSProgressIndicator的NSCell版本,但是AppKit没有这样的东西。对于类似的问题,在Daniel Jalkut's answer中描述的解决方案可能是您想要的最快的路径。这是基本的想法:
观察项目的refreshing状态,而不是在绘图过程中使用refreshing变量切换路径。当它变为真时,在给定frameOfCellAtColumn:row:的项目位置添加一个NSProgressIndicator作为NSOutlineView的子视图(为最右侧的进度指示器设置一个列可能更方便)。当它变为false时,删除相应的进度指示器。您还需要确保在这些进度指示器上适当地设置自动调整大小标志,以便它们随着大纲视图的大小调整而移动。
https://stackoverflow.com/questions/6330776
复制相似问题