如何创建一个简单的基于视图的NSOutlineView?

12

为了学习目的,我想将基于单元格的NSOutlineView转换为基于视图的NSOutlineView,

基本上我希望如下:

  • 不使用普通单元格,而是使用“图像和文本表格单元视图”
  • 图像可以是标准的NSApplicationIcon,文本可以是“hello world” :)
  • 不使用绑定和NSTreeController来完成这个功能

这里有一个“世界上最简单的NSOutlineView”示例http://www.cocoasteam.com/Cocoa_Steam/Worlds_Simplest_Demo.html

我想知道有没有人能够修改它,使其成为基于视图的,并按照我上面说的工作 :) :)

我已经尝试查看苹果的示例和在互联网上搜索,但仍然无法使其正常工作 - 所以非常感谢您提前的帮助 :)

4个回答

9
我创建了一个小示例项目,可以做到以下几点:
  • 显示一系列项目
  • 以主从式编辑项目
  • 删除和添加项目
  • 使用绑定
请查看github上的besi/mac-quickies。 大部分内容都是在IB中完成的,或者可以在AppDelegate中找到。

screenshot


2
这是一个非常易于理解的示例。谢谢。 - JeremyP

8

好的,你需要一个带有ImageAndTextCell的NSOutlineView,对吧?

让我们来做这类问题中最典型的例子:一个简单的文件浏览器。

我们需要:

  • 一个NSOutlineView(将大纲视图放到AppDelegate中,命名为fileOutlineView)
  • 在大纲视图中创建三个列,使用以下标识符(在Interface Builder中进行设置):NameColumn、SizeColumn和ModifiedColumn

现在,至于其余部分,我都会通过编程来完成,以便让您了解正在发生的事情...

如何设置它(例如在- (void)awakeFromNib中):

// set the Data Source and Delegate
[fileOutlineView setDataSource:(id<NSOutlineViewDataSource>)self];
[fileOutlineView setDelegate:(id<NSOutlineViewDelegate>)self];

// set the first column's cells as `ImageAndTextCell`s
ImageAndTextCell* iatc = [[ImageAndTextCell alloc] init];
[iatc setEditable:NO];
[[[fileOutlineView tableColumns] objectAtIndex:0] setDataCell:iatc];

连接各个点:

/*******************************************************
 *
 * OUTLINE-VIEW DATASOURCE
 *
 *******************************************************/

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{        
    if ([item isFolder])
        return YES;
    else
        return NO;
}

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{    
    if (item==nil)
    {
        // Root
        return [[filePath folderContentsWithPathAndBackIgnoringHidden] count];
    }
    else
    {        
        if ([item isFolder])
        {
            return [[item folderContentsWithPathAndBackIgnoringHidden] count];
        }
        else
        {
            return 0;
        }
    }
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
    if (item == nil)
    { 
        // Root
        return [[filePath folderContentsWithPathAndBackIgnoringHidden] objectAtIndex:index];
    }

    if ([item isFolder])
    {
        return [[item folderContentsWithPathAndBackIgnoringHidden] objectAtIndex:index];
    }

    // File
    return nil;
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)theColumn byItem:(id)item
{          
    if ([[theColumn identifier] isEqualToString:@"NameColumn"])
    {
        return [item lastPathComponent];
    }
    else if ([[theColumn identifier] isEqualToString:@"SizeColumn"])
    {
        if ([item isFolder]) return @"--";
        else return [NSString stringWithFormat:@"%d",[item getFileSize]];
    }
    else if ([[theColumn identifier] isEqualToString:@"ModifiedColumn"])
    {
        if ([item isFolder]) return @"";
        else return [NSString stringWithFormat:@"%@",[item getDateModified]];
    }

    // Never reaches here
    return nil;
}

/*******************************************************
 *
 * OUTLINE-VIEW DELEGATE
 *
 *******************************************************/

- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item
{
    return YES;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
{
    return NO;
}

- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
    [cell setDrawsBackground:NO];

    if ([item isFileHidden]) [cell setTextColor:[NSColor grayColor]];
    else [cell setTextColor:[NSColor whiteColor]];

    if ([[tableColumn identifier] isEqualToString:@"NameColumn"])
    {
        if ([item isFolder])
            [cell setImage:[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)] size:15.0];
        else
            [cell setImage:[[NSWorkspace sharedWorkspace] iconForFile:item] size:15.0];

        if ([item isFileHidden])
        {
            [cell setFileHidden:YES];
        }
        else
        {
            [cell setFileHidden:NO];
        }

    }

}

提示: ImageAndTextCell 类可在这里找到。您还会注意到我使用了其他一些方法,这些方法显然不受Cocoa支持(例如isFileHiddenisFolderfolderContentsWithPathAndBackIgnoringHidden),但是自己实现它们并不难...)


20
我不认为这是正确的。ImageAndTextCell 是 NSCell 类型,而不是 NSView。问题是关于基于视图的 NSOutlineView 的。你的示例只是关于创建自定义的 NSCell 子类,而我们已经能够做到这一点多年了。对于 NSTableView,有很多使用 NSView 而不是 NSCell 的示例。看起来很像 iOS。可惜我没有找到任何 NSOutlineView 的示例。 - Erik Engheim
1
@Adam- 基于视图的表格使用NSTableCellViews作为它们的视图。从那里,您可以添加任何内容。Dr.Kameleon所说的完全正确。基于视图的表格的整个重点在于,您可以添加任何想要的视图对象(无论是单元格、按钮、图像等)。 - Patrick
2
这不是关于创建基于视图的大纲视图。 - JeremyP

1

将视图返回到OutlineView列,而不是使用返回objectValue的数据源方法:

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)theColumn byItem:(id)item

使用返回视图的数据源方法!!!!!
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item

其它的都一样(最低要求是前三个数据源方法,不需要代理方法),但是不能使用willdisplaycell,因为它仅适用于基于单元格的情况,在viefortablecolumn方法中完成视图的所有操作,如下:

if ([[tableColumn identifier] isEqualToString:@"YourColumnIdentifier"]){
    NSTableCellView *cell = [outlineView makeViewWithIdentifier:@"YourViewsIdentifier" owner:self];
    [cell.textField setStringValue:[(YourItem *)item name]];
    [cell.imageView setImage:[(YourItem *)item image]];
    return cell;
}

return nil;

不要忘记设置标识符,并将OutlineView设置为基于视图的(在IB中...)。

好的,这个可以工作,但结果非常丑陋。OutlineView出现在视图后面:所以,这与基于视图的NSTableView不完全相同。 - Chrstpsln

0

请查看TableViewPlayground,还可以参考2011年WWDC的基础到高级的View Based NSTableView


3
谢谢,我已经查看了那个例子,但我认为它太冗长和令人困惑了。我需要一个非常简单的例子来理解它(我对Cocoa也有点陌生 :P)。 - horseyguy

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