Я использую опцию "Alternating Rows" в Interface Builder для получения чередующихся цветов строк в NSTableView. Есть ли способ изменить цвета чередующихся строк?
Изменение цвета строки NSTableView
Ответ 1
Найден лучший способ сделать это здесь. Этот метод переопределяет метод highlightSelectionInClipRect: в подклассе NSTableView, поэтому вы можете использовать любой цвет, который вы хотите для чередующихся строк. Это не так хакерски, как использование категории NSColor, и оно влияет только на выбранные вами таблицы.
Ответ 2
Если вы хотите использовать недокументированный способ, введите категорию NSColor
и переопределите _blueAlternatingRowColor
следующим образом:
@implementation NSColor (ColorChangingFun)
+(NSColor*)_blueAlternatingRowColor
{
return [NSColor redColor];
}
@end
или изменить оба цвета, переопределить controlAlternatingRowBackgroundColors
, чтобы вернуть массив цветов, которые вы хотите чередовать.
@implementation NSColor (ColorChangingFun)
+(NSArray*)controlAlternatingRowBackgroundColors
{
return [NSArray arrayWithObjects:[NSColor redColor], [NSColor greenColor], nil];
}
@end
Ответ 3
Я подклассифицировал NSTableView и реализовал drawRow: clipRect: вот так...
- (void)drawRow:(NSInteger)row clipRect:(NSRect)clipRect
{
NSColor *color = (row % 2) ? [NSColor redColor] : [NSColor whiteColor];
[color setFill];
NSRectFill([self rectOfRow:row]);
[super drawRow:row clipRect:clipRect];
}
Кажется, что это работает, но это так просто, что мне интересно, не хватает ли чего-то.
Ответ 4
Я не уверен, как недавно это было добавлено, или если оно так же гибко, как вам нужно, но я заметил, что вы можете указать "чередующиеся" строки в Interface Builder в Xcode 4.6 (и, возможно, раньше).
- Откройте nib в Xcode и выберите
NSTableView
илиNSOutlineView
- Показать инспектор атрибутов в панели "Утилиты" (⎇⌘4)
- Обратите внимание на флажок
Highlight Alternating Rows
.
Ответ 5
Мне нужно решение, которое работало точно так же, как и обычный NSTableView
, включая поддержку прокрутки прокрутки и т.д., поэтому я создал подкласс NSTableView
, который имеет свойство NSColor*
, называемое alternateBackgroundColor
, а затем переопределяет -drawBackgroundColorInClipRect:
так:
- (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 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 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;
}
}
}
}
Ответ 6
Для этого нет настраиваемого свойства, однако вы можете ответить на метод делегата -tableView:willDisplayCell:forTableColumn:row:
и установить цвет фона ячейки на основе равномерности номера строки.
Ответ 7
Nate Thorn ответ работал отлично для меня.
Вот он, реорганизован для 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 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 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
}
}
}
}
Ответ 8
Свифт 4+ версия ответа AlternateRealist:
public class AlternateBgColorTableView: NSTableView {
var alternateBackgroundColor: NSColor? = .red
override public func drawBackground(inClipRect clipRect: NSRect) {
// If we didn't set the alternate color, fall back to the default behavior
guard let alternateBackgroundColor = alternateBackgroundColor else {
super.drawBackground(inClipRect: clipRect)
return
}
// Fill in the background color
backgroundColor.set()
clipRect.fill()
// Check if we should be drawing alternating colored rows
if usesAlternatingRowBackgroundColors {
// Set the alternating background color
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.height
let rowsToDraw = rows(in: checkRect)
var currentRow = rowsToDraw.location
repeat {
if currentRow % 2 != 0 {
// This is an alternate row
var rowRect = rect(ofRow: currentRow)
rowRect.origin.x = clipRect.origin.x
rowRect.size.width = clipRect.width
rowRect.fill()
}
currentRow += 1
} while currentRow < rowsToDraw.location + rowsToDraw.length
// Figure out the height of "off the table" rows
var thisRowHeight = rowHeight
if gridStyleMask.contains(.solidHorizontalGridLineMask) || gridStyleMask.contains(.dashedHorizontalGridLineMask) {
thisRowHeight += 2 // Compensate for a grid
}
// Draw fake rows below the table last row
var virtualRowOrigin: CGFloat = 0
var virtualRowNumber = numberOfRows
if numberOfRows > 0 {
let finalRect = rect(ofRow: numberOfRows - 1)
virtualRowOrigin = finalRect.origin.y + finalRect.height
}
repeat {
if virtualRowNumber % 2 != 0 {
// This is an alternate row
let virtualRowRect = NSRect(x: clipRect.origin.x, y: virtualRowOrigin, width: clipRect.width, height: thisRowHeight)
virtualRowRect.fill()
}
virtualRowNumber += 1
virtualRowOrigin += thisRowHeight
} while virtualRowOrigin < clipRect.origin.y + clipRect.size.height
// Draw fake rows above the table 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.width, height: thisRowHeight)
virtualRowRect.fill()
}
virtualRowNumber -= 1
virtualRowOrigin -= thisRowHeight
} while virtualRowOrigin + thisRowHeight > clipRect.origin.y
}
}
}