【问题标题】:Draw grid lines in NSTableView only for populated rows?仅在 NSTableView 中为填充的行绘制网格线?
【发布时间】:2019-08-20 21:22:20
【问题描述】:

如何在 NSTableView 中仅为已填充的行绘制网格线?当我将网格样式掩码设置为 NSTableViewSolidHorizo​​ntalGridStyleMask 时,它会为所有行绘制网格线,无论是否填充。

我正在寻找一些示例代码来执行此操作。

【问题讨论】:

    标签: cocoa


    【解决方案1】:

    到目前为止,我发现最适合我的是以下代码。只需欺骗原始网格绘图代码,使其仅在填充的行上绘图。

    如果需要,子类 NSTableView,并覆盖 drawGridInClipRect:(NSRect)clipRect,如下所示:

    - (void)drawGridInClipRect:(NSRect)clipRect
    {
        NSRect lastRowRect = [self rectOfRow:[self numberOfRows]-1];
        NSRect myClipRect = NSMakeRect(0, 0, lastRowRect.size.width, NSMaxY(lastRowRect));
        NSRect finalClipRect = NSIntersectionRect(clipRect, myClipRect);
        [super drawGridInClipRect:finalClipRect];
    }
    

    【讨论】:

    • 不是像上面那样计算myClipRect,你能不能这样做:NSRect finalClipRect = NSIntersectionRect(clipRect, self.bounds)?
    • @sam 你可以试试这个,但我相信它不会起作用。它不考虑最后一行的位置。 Self 是表视图,它可能高于表中的所有行。实际上,根据定义,clipRect 应该已经小于或等于 self.bounds。
    • 这会创建一个黑色视图来代替空白区域。我在更新 5.0.1 的 xcode 时注意到了这个问题。有更新的答案吗?
    • 为了在最后一列之后裁剪网格,您可以使用:NSRect lastColumnRect = [self rectOfColumn:self.numberOfColumns - 1]; NSRect finalClipRect = NSMakeRect(0, 0, NSMaxX(lastColumnRect), NSMaxY(lastRowRect));
    • 我正在寻找另一种解决方案。我想禁用部分的网格线。我不想让它为部分绘制。我只希望它们在细胞之间。有什么想法吗??
    【解决方案2】:

    在 Swift 3.1 中,这就是你所需要的:

    import Cocoa
    
    class GridClipTableView: NSTableView {
    
        override func drawGrid(inClipRect clipRect: NSRect) { }
    
    }
    

    【讨论】:

    • 与 Obj-C 相同:使用空方法覆盖 drawGridInClipRect:,仅绘制项目网格。
    • 这很完美——而且比其他解决方案更干净!
    【解决方案3】:

    我认为您必须继承 NSTableView 并覆盖 drawRow:clipRect:。另一种可能性是覆盖drawGridInClipRect:,但这有点笨拙,因为您必须手动选择行。

    这应该会让你朝着正确的方向前进:

    - (void)drawRow:(NSInteger)rowIndex clipRect:(NSRect)clipRect {
        // First do the default drawing
        [super drawRow:rowIndex clipRect:clipRect];
    
        // Check if there's content in any of the cells in this row
        BOOL doesHaveContent = NO;
        int numCols = [self numberOfColumns];
        int colIndex;
        for( colIndex = 0; colIndex < numCols; colIndex++ ){
            NSCell * cell = [self preparedCellAtColumn:colIndex 
                                                   row:rowIndex];
            if( [cell objectValue] != nil ){
                doesHaveContent = YES;
                break;
            }
        }
    
        if( doesHaveContent ){
            NSRect rowRect = [self rectOfRow:rowIndex];
            NSBezierPath * gridPath = [NSBezierPath bezierPath];
            // Ignoring clipRect because this isn't a lot of drawing
            [gridPath moveToPoint:rowRect.origin];
            [gridPath lineToPoint:NSMakePoint(rowRect.origin.x + rowRect.size.width,
                                              rowRect.origin.y)];
            [gridPath moveToPoint:NSMakePoint(rowRect.origin.x,
                                              rowRect.origin.y + rowRect.size.height)];
            [gridPath lineToPoint:NSMakePoint(rowRect.origin.x + rowRect.size.width,
                                              rowRect.origin.y + rowRect.size.height)];
            [myGridColor set];
            [gridPath stroke];
            // You could also just do:
            // [myGridColor set];
            // [[NSBezierPath bezierPathWithRect:rowRect] stroke];
        }
    }
    

    另一种可能性是自定义NSCell;如果有内容,每个单元格都可以在其周围绘制一个特殊的边框。但是,如果该行中有一些单元格是空的,这不会在整行上画一条线。

    【讨论】:

    • 另一种可能性是根据数据源中的实际行数调整表格视图的大小。
    • @Bavarious:说得好,但在我看来,OP 希望出现空行,而不是内衬。
    • 根本不适合我。根本不调用 DrawRow 方法:(
    【解决方案4】:

    出于某种原因,此处列出的解决方案都不适合我。我所做的是:

    1. 子类NSTableView 并覆盖rectOfColumn:(见下文)。
    2. 在表格视图、剪辑视图和滚动视图上打开图层支持(此解决方案需要这样做)。

    在我的测试中,这适用于 macOS 10.9 到 10.15。

    - (NSRect)rectOfColumn:(NSInteger)column
    {
        NSRect value = [super rectOfColumn:column];
    
        NSInteger numberOfRows = [self numberOfRows];
        if (numberOfRows == 0) {
            value.size.height = 0;
        } else {
            NSRect firstRect = [self rectOfRow:0];
            NSRect lastRect = [self rectOfRow:numberOfRows - 1];
    
            value.size.height = NSMaxY(lastRect) - NSMinY(firstRect);
        }
    
        return value;
    }
    

    【讨论】:

    • 这种方法也切断了列分隔符,而另一种方法让它们被绘制到表格的底部。
    猜你喜欢
    • 1970-01-01
    • 2018-08-19
    • 2013-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    相关资源
    最近更新 更多