NSOutlineView:删除显示三角形和缩进

时间:2010-11-23 01:05:33

标签: objective-c cocoa nsoutlineview nstreecontroller

我正在使用NSOutlineView进行项目,似乎无法弄清楚两件事:

  • 如何删除树节点的显示三角形。像iTunes这样的应用似乎能够做到这一点:

alt text

是否有某种用于此的NSOutlineView Delegate方法?或者它需要一个子类?

  • 如何禁用项目缩进。我尝试使用 setIndentationPerLevel:并将其设置为0,以及在Interface Builder中将列缩进更改为0,但它似乎没有任何效果。

8 个答案:

答案 0 :(得分:40)

你在这里遇到了合适的人选。一周前我不得不解决这个问题。

删除显示三角形:在frameOfOutlineCellAtRow:子类中实现NSOutlineView方法并返回NSZeroRect(仅当您要隐藏该特定行的三角形时,当然。)

- (NSRect)frameOfOutlineCellAtRow:(NSInteger)row {
    return NSZeroRect;
}

禁用缩进:大纲视图的标准布局保留最左侧的空间以绘制三角形,以防项目可扩展。但您可以通过指定不同的绘图框来覆盖单个项目。您也可以通过响应此消息在您的子类中执行此操作:

- (NSRect)frameOfCellAtColumn:(NSInteger)column row:(NSInteger)row {
    NSRect superFrame = [super frameOfCellAtColumn:column row:row];


    if ((column == 0) /* && isGroupRow */) {
        return NSMakeRect(0, superFrame.origin.y, [self bounds].size.width, superFrame.size.height);
    }
    return superFrame;
}

答案 1 :(得分:35)

为了将来参考,在可扩展的NSOutlineView项中隐藏显示三角形的最简洁和最简单的方法是在您的代理中实施outlineView:shouldShowOutlineCellForItem:协议的NSOutlineViewDelegate方法:

-(BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item
{
    // replace this with your logic to determine whether the
    // disclosure triangle should be hidden for a particular item
    return [item hidesDisclosureTriangle];
}

答案 2 :(得分:8)

我必须将上述两种方法结合起来,因为outlineView:shouldShowOutlineCellForItem:单独不会删除为显示三角形保留的空间(它确实会删除三角形本身)。

代表:

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

NSOutlineView的子类:

@implementation ExpandedOutlineView

#define kOutlineCellWidth 11
#define kOutlineMinLeftMargin 6

- (NSRect)frameOfCellAtColumn:(NSInteger)column row:(NSInteger)row {
    NSRect superFrame = [super frameOfCellAtColumn:column row:row];
    if (column == 0) {
        // expand by kOutlineCellWidth to the left to cancel the indent
        CGFloat adjustment = kOutlineCellWidth;

        // ...but be extra defensive because we have no fucking clue what is going on here
        if (superFrame.origin.x - adjustment < kOutlineMinLeftMargin) {
            NSLog(@"%@ adjustment amount is incorrect: adjustment = %f, superFrame = %@, kOutlineMinLeftMargin = %f", NSStringFromClass([self class]), (float)adjustment, NSStringFromRect(superFrame), (float)kOutlineMinLeftMargin);
            adjustment = MAX(0, superFrame.origin.x - kOutlineMinLeftMargin);
        }

        return NSMakeRect(superFrame.origin.x - adjustment, superFrame.origin.y, superFrame.size.width + adjustment, superFrame.size.height);
    }
    return superFrame;
}

@end

结果:

Screenshot of NSOutlineView with no top-level indentation

答案 3 :(得分:2)

使用PXSourceList。这是你正在寻找的风格非常好的api。

答案 4 :(得分:0)

指定每个级别的意图的正确方法是覆盖NSOutlineView的indentationPerLevel

class NoIndentOutlineView: NSOutlineView {
    override var indentationPerLevel: CGFloat {
        get {
            return 0;
        }
        set {
            // Do nothing
        }
    }
}

这将确保孩子的缩进与父母相同。

答案 5 :(得分:0)

这与隐藏披露按钮有关。如果您希望将其全局隐藏在可扩展项目上,则可以执行以下操作:

extension NSOutlineView {
    override open func makeView(withIdentifier identifier: NSUserInterfaceItemIdentifier, owner: Any?) -> NSView? {
        if identifier == NSOutlineView.disclosureButtonIdentifier {
            return nil
        } else {
            return super.makeView(withIdentifier: identifier, owner: owner)
        }
    }
}

否则,您可以继承NSOutlineView的子类并覆盖makeView函数。

我知道q是obj-c。我只需要解决这个问题,我的项目就很快。

答案 6 :(得分:0)

对于OP提出的问题,以上给出了很好的答案-删除了显示三角形及其占用的空间。要实现“列表不扩展且所有项目都在同一级别”(即它们要达到的效果),您需要做的就是将大量顶级项目放入用作数据的数组中源和实现

func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
    return false
}

答案 7 :(得分:-3)

我在Swift中试过这个。它只是有效。我不知道这是否是一种正确的方式。在Obj-C中应该有相同的东西:

extension NSTableRowView {
    override open func layout() {
        super.layout()
        if let cell = subviews.first as? NSTableCellView, cell.objectValue is <YourHeaderCellClass> {
            subviews.first?.setFrameOrigin(NSZeroPoint)
        }
    }
}

确保在datasource方法中返回YourHeaderCellClass项。

func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any