2010-10-20 2 views

ответ

7

Найден лучший способ сделать это here. Этот метод переопределяет метод highlightSelectionInClipRect: в подклассе NSTableView, поэтому вы можете использовать любой цвет, который вы хотите для чередующихся строк. Это не так хакерски, как использование категории NSColor, и это влияет только на вид таблиц, которые вы выбираете.

+1

+100 Я наткнулся на этот вопрос несколько дней назад, надеясь на хороший ответ, но не нашел удовлетворительного. К счастью, мне довелось увидеть его снова! Благодаря! –

+1

Это не работало для меня. Он выглядит отлично, если вы не начнете прокручивать вверх и вниз с помощью полосы прокрутки. Затем перерисовывается, и вы получаете множество горизонтальных белых линий в цветных рядах. Я поставил свою реализацию ниже, но это так просто, что я задаюсь вопросом, не хватает ли я чего-то. – sam

1

Для этого нет подходящего свойства, однако вы можете ответить на метод делегата -tableView:willDisplayCell:forTableColumn:row: и установить цвет фона ячейки на основе четности номера строки.

+2

Это, кажется, не работает, когда нет клеток в виде таблицы (не изменить цвет фона самого табличном) – indragie

7

Если вы хотите использовать недокументированные путь, сделать 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 
+1

Почему хак когда API дает вам способ? –

+0

um, потому что это весело;) ROFL –

+0

Это работает, но он меняет только один из цветов. – indragie

4

I подклассы 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]; 
} 

Это похоже на работу, но это так просто, что мне интересно, если я что-то не хватает.

+3

К сожалению, он не предоставляет чередующиеся цвета для пустых строк, только строки, содержащие данные. – Huperniketes

+1

Это сработало для меня. Вы можете обернуть первые три строки в 'if (row! = [Self selectedRow])', чтобы предотвратить проблемы с выделенным фоном выбранных строк. – pepsi

+1

@ Huperniketes Проверьте [этот вопрос] (http://stackoverflow.com/questions/14178370/draw-nstableview-alternating-rows-like-itunes-11?rq=1) для решения также пользовательского рисования фона таблицы без строк – Jay

1

Я хотел решения, которое работало так же, как обычная 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'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

Чтобы выполнить эту работу, мне пришлось отключить использованиеAlternatingRowBackgroundColors и выполнить условную проверку. В противном случае представление таблицы было сверху, и я видел только рисованные виртуальные строки за пределами табличных границ. – greg

3

Я не уверен, как недавно это было добавлено, или если оно столь же гибко, как вам нужно, но я заметил, что вы можете указать «чередующиеся» строки в Interface Builder в Xcode 4.6 (и, возможно, раньше) ,

  1. Откройте перо в Xcode и выберите NSTableView или NSOutlineView
  2. Показать атрибуты инспектора в панели Utilities (⎇⌘4)
  3. Обратите внимание на Highlight Alternating Rows флажок.

enter image description here

+0

Да, это вариант, который я использовал (это было какое-то время). Проблема заключалась в том, чтобы настраивать переменные цвета, так как тикание этого окна дает вам только цвета синей/белой системы по умолчанию. – indragie

0

Nate Thorn «s answer работал отлично для меня.

Вот она, переработан для 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 
      } 
     } 
    } 
} 
Смежные вопросы