Change NSTableView alternate row colors

前端 未结 9 1208

I\'m using the \"Alternating Rows\" option in Interface Builder to get alternating row colors on an NSTableView. Is there any way to change the colors of the alternating row

相关标签:
9条回答
  • 2020-12-28 17:50

    Found a better way to do it here. That method overrides the highlightSelectionInClipRect: method in an NSTableView subclass so you can use any color you want for the alternating rows. It's not as hackish as using an NSColor category, and it only affects table views you choose.

    0 讨论(0)
  • 2020-12-28 17:55

    I wanted a solution that worked just like the regular NSTableView, including support for elastic scrolling and such, so I created an NSTableView subclass that has an NSColor* property called alternateBackgroundColor, and then overrode the -drawBackgroundColorInClipRect: method like so:

    - (void) drawBackgroundInClipRect:(NSRect)clipRect {
        if([self alternateBackgroundColor] == nil) {
            // If we didn't set the alternate colour, fall back to the default behaviour
            [super drawBackgroundInClipRect:clipRect];
        } else {
            // Fill in the background colour
            [[self backgroundColor] set];
            NSRectFill(clipRect);
    
            // Check if we should be drawing alternating coloured rows
            if([self alternateBackgroundColor] && [self usesAlternatingRowBackgroundColors]) {
                // Set the alternating background colour
                [[self alternateBackgroundColor] set];
    
                // Go through all of the intersected rows and draw their rects
                NSRect checkRect = [self bounds];
                checkRect.origin.y = clipRect.origin.y;
                checkRect.size.height = clipRect.size.height;
                NSRange rowsToDraw = [self rowsInRect:checkRect];
                NSUInteger curRow = rowsToDraw.location;
                while(curRow < rowsToDraw.location + rowsToDraw.length) {
                    if(curRow % 2 != 0) {
                        // This is an alternate row
                        NSRect rowRect = [self rectOfRow:curRow];
                        rowRect.origin.x = clipRect.origin.x;
                        rowRect.size.width = clipRect.size.width;
                        NSRectFill(rowRect);
                    }
    
                    curRow++;
                }
    
                // Figure out the height of "off the table" rows
                CGFloat rowHeight = [self rowHeight];
                if( ([self gridStyleMask] & NSTableViewSolidHorizontalGridLineMask) == NSTableViewSolidHorizontalGridLineMask
                   || ([self gridStyleMask] & NSTableViewDashedHorizontalGridLineMask) == NSTableViewDashedHorizontalGridLineMask) {
                    rowHeight += 2.0f; // Compensate for a grid
                }
    
                // Draw fake rows below the table's last row
                CGFloat virtualRowOrigin = 0.0f;
                NSInteger virtualRowNumber = [self numberOfRows];
                if([self numberOfRows] > 0) {
                    NSRect finalRect = [self rectOfRow:[self numberOfRows]-1];
                    virtualRowOrigin = finalRect.origin.y + finalRect.size.height;
                }
                while(virtualRowOrigin < clipRect.origin.y + clipRect.size.height) {
                    if(virtualRowNumber % 2 != 0) {
                        // This is an alternate row
                        NSRect virtualRowRect = NSMakeRect(clipRect.origin.x,virtualRowOrigin,clipRect.size.width,rowHeight);
                        NSRectFill(virtualRowRect);
                    }
    
                    virtualRowNumber++;
                    virtualRowOrigin += rowHeight;
                }
    
                // Draw fake rows above the table's first row
                virtualRowOrigin = -1 * rowHeight;
                virtualRowNumber = -1;
                while(virtualRowOrigin + rowHeight > clipRect.origin.y) {
                    if(abs(virtualRowNumber) % 2 != 0) {
                        // This is an alternate row
                        NSRect virtualRowRect = NSMakeRect(clipRect.origin.x,virtualRowOrigin,clipRect.size.width,rowHeight);
                        NSRectFill(virtualRowRect);
                    }
    
                    virtualRowNumber--;
                    virtualRowOrigin -= rowHeight;
                }
            }
        }
    }
    
    0 讨论(0)
  • Nate Thorn's answer worked perfectly for me.

    Here it is, refactored for Swift:

    import Foundation
    import Cocoa
    import AppKit
    
    public class SubclassedTableView : NSTableView {
    
        private func
        alternateBackgroundColor() -> NSColor? {
            return NSColor.redColor() // Return any color you like
        }
    
        public override func
        drawBackgroundInClipRect(clipRect: NSRect) {
    
            if alternateBackgroundColor() == nil {
                // If we didn't set the alternate colour, fall back to the default behaviour
                super.drawBackgroundInClipRect(clipRect)
            } else {
                // Fill in the background colour
                self.backgroundColor.set()
                NSRectFill(clipRect)
    
                // Check if we should be drawing alternating coloured rows
                if usesAlternatingRowBackgroundColors {
                    // Set the alternating background colour
                    alternateBackgroundColor()!.set()
    
                    // Go through all of the intersected rows and draw their rects
                    var checkRect = bounds
                    checkRect.origin.y = clipRect.origin.y
                    checkRect.size.height = clipRect.size.height
                    let rowsToDraw = rowsInRect(checkRect)
                    var curRow = rowsToDraw.location
                    repeat {
                        if curRow % 2 != 0 {
                            // This is an alternate row
                            var rowRect = rectOfRow(curRow)
                            rowRect.origin.x = clipRect.origin.x
                            rowRect.size.width = clipRect.size.width
                            NSRectFill(rowRect)
                        }
    
                        curRow++
                    } while curRow < rowsToDraw.location + rowsToDraw.length
    
                    // Figure out the height of "off the table" rows
                    var thisRowHeight = rowHeight
                    if gridStyleMask.contains(NSTableViewGridLineStyle.SolidHorizontalGridLineMask)
                       || gridStyleMask.contains(NSTableViewGridLineStyle.DashedHorizontalGridLineMask) {
                        thisRowHeight += 2.0 // Compensate for a grid
                    }
    
                    // Draw fake rows below the table's last row
                    var virtualRowOrigin = 0.0 as CGFloat
                    var virtualRowNumber = numberOfRows
                    if numberOfRows > 0 {
                        let finalRect = rectOfRow(numberOfRows-1)
                        virtualRowOrigin = finalRect.origin.y + finalRect.size.height
                    }
                    repeat {
                        if virtualRowNumber % 2 != 0 {
                            // This is an alternate row
                            let virtualRowRect = NSRect(x: clipRect.origin.x, y: virtualRowOrigin, width: clipRect.size.width, height: thisRowHeight)
                            NSRectFill(virtualRowRect)
                        }
    
                        virtualRowNumber++
                        virtualRowOrigin += thisRowHeight
                    } while virtualRowOrigin < clipRect.origin.y + clipRect.size.height
    
                    // Draw fake rows above the table's first row
                    virtualRowOrigin = -1 * thisRowHeight
                    virtualRowNumber = -1
                    repeat {
                        if abs(virtualRowNumber) % 2 != 0 {
                            // This is an alternate row
                            let virtualRowRect = NSRect(x: clipRect.origin.x, y: virtualRowOrigin, width: clipRect.size.width, height: thisRowHeight)
                            NSRectFill(virtualRowRect)
                        }
    
                        virtualRowNumber--
                        virtualRowOrigin -= thisRowHeight
                    } while virtualRowOrigin + thisRowHeight > clipRect.origin.y
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题