如何在NSOutlineView中重新加载自定义NSTableRowView?

5

我正在尝试修改自定义NSTableRowView在NSOutlineView中行展开/折叠时的外观。我的NSOutlineViewDelegate包括:

- (NSTableRowView *)outlineView:(NSOutlineView *)outlineView rowViewForItem:(id)item
{
    ...
    return rowView;
}

- (void)itemDidExpand:(NSNotification *)notification
{
    NSDictionary *userInfo = [notification userInfo];
    id item = [userInfo objectForKey:@"NSObject"];
    NSOutlineView *outlineView = [notification object];
    [outlineView reloadItem:item];
}

很遗憾,这无法重新加载自定义行视图。

重新加载整个NSOutlineView的数据可以解决问题:

- (void)itemDidExpand:(NSNotification *)notification
{
    [outlineView reloadData];
}

但是当处理大量数据时,这可能会耗费很长时间,并且经常导致出现旋转的沙滩球。

是否可以仅为单个顶级项目重新加载自定义行视图?


你是想修改颜色或者其他什么吗? - Just a coder
是的,自定义表格行视图重写了drawSeparatorInRect:和drawBackgroundInRect:方法,根据项目是否展开或折叠来更改颜色。 - JM NZ
我在下面提供了一个解决方案。如果有效,请告诉我。 - Just a coder
2个回答

6

可以尝试以下方法:

-(void)outlineView:(NSOutlineView *)outlineView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row {
    aColor = [NSColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0];
    [view setBackgroundColor:aColor];
}

你可以进一步获取行对象,然后确定特定行所需的颜色。
-编辑-
如果你希望更改父单元格视图以显示其已展开,那么你实现NSOutlineview的方法是错误的。请像下面这样实现该方法:
-(void)outlineViewItemWillExpand:(NSNotification *)notification {
    id theObject = [[notification userInfo] objectForKey:@"NSObject"];

    NSInteger row = [theOutlineView rowForItem:theObject];
    NSTableRowView *theRowView = [theOutlineView rowViewAtRow:row makeIfNecessary:NO];

    int r = 110;
    int g = 110;
    int b = 110;

    NSColor *aColor = [NSColor colorWithCalibratedRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:1.0];
    [theRowView setBackgroundColor:aColor];
}

谢谢Jai,我尝试了这个方法,但不幸的是outlineView:didAddRowView:forRow:只在子行上调用,而不是正在展开/折叠的行。 - JM NZ
我有点困惑 (1) 难道被展开/折叠的行不是子行吗?(2) 这个在任何行被添加时都会触发。你能提供一些代码吗? - Just a coder
父行包含披露三角形 - 当单击它时,它会展开并显示子行。此时,我想更改父行的背景颜色以指示已展开。然而,不幸的是,到目前为止,我唯一能够实现这一点的方法是在整个NSOutlineView上调用reloadData。我正在寻找一种方法,可以强制仅重绘父行的自定义rowView,而无需重新加载整个表格。 - JM NZ
非常感谢您,@Jai!从outlineViewWillExpand调用rowViewAtRow:makeIfNecessary正是所需的。 - JM NZ

1
在您的rowViewForItem方法中尝试此操作。它重新加载并显示项目的数据。
    - (void)reloadItem:(id)item;

1
rowViewForItem对于这一行没有再次被调用 - 这就是我想要触发的。我从itemDidExpand中调用reloadItem,它正在重新加载子行的行视图,但不是正在扩展的行,需要更改外观的行。 - JM NZ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接