我有一个NSOutlineView,它使用自定义NSCell子类来绘制NSProgressIndicator。每个NSCell都有一个refreshing
属性,由NSOutlineView委托willDisplayCell:forItem:
方法设置,如下所示:
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
cell.refreshing = item.refreshing;
}
每个项目实例都包含一个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];
}
}
NSProgressIndicator实例在NSCell的drawInteriorWithFrame:inView:
类中停止并启动,如下所示:
- (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。
我在这里做错了什么?
答案 0 :(得分:0)
在绘制事物的过程中弄乱视图层次结构是不好的做法。最好的办法是使用NSCell
版NSProgressIndicator
,但AppKit
没有这样的东西。 Daniel Jalkut's answer中描述的类似问题的解决方案可能是您想要的最快路径。这是基本的想法:
不要使用refreshing
变量在绘图期间切换路径,而是观察项目的“refreshing
状态”。如果成为现实,请在NSProgressIndicator
的项目位置添加NSOutlineView
作为frameOfCellAtColumn:row:
的子视图(可以方便地为最右侧的进度指示器设置列)。当它变为false时,删除相应的进度指示器。您还需要确保在这些进度指示器上适当地设置自动调整标记,以便它们随着大纲视图的调整大小而移动。