2010-10-20 13 views

Respuesta

7

Encontré una mejor manera de hacerlo here. Ese método anula el método highlightSelectionInClipRect: en una subclase NSTableView para que pueda usar cualquier color que desee para las filas alternas. No es tan hackish como usar una categoría NSColor, y solo afecta las vistas de tabla que elijas.

+1

+100 Me encontré con esta pregunta hace unos días con la esperanza de obtener una buena respuesta, pero no encontré una respuesta satisfactoria. ¡Afortunadamente, sucedió que lo volví a ver! ¡Gracias! –

+1

Esto no funcionó para mí. Se ve bien a menos que empiece a desplazarse hacia arriba y hacia abajo con la barra de desplazamiento. Luego el re-dibujo se arruina y se termina con muchas líneas blancas horizontales en las filas de colores. Puse mi implementación a continuación, pero es tan simple que me pregunto si me estoy perdiendo algo. – sam

1

No hay una propiedad configurable para esto, sin embargo, puede responder al método delegado -tableView:willDisplayCell:forTableColumn:row: y establecer el color de fondo de la celda según la uniformidad del número de fila.

+2

Esto no parece funcionar cuando no hay células en la vista de tabla (no cambia el fondo de la propia vista de tabla) – indragie

7

Si desea utilizar una forma no documentada, crea una categoría NSColor y anular _blueAlternatingRowColor así:

@implementation NSColor (ColorChangingFun) 

+(NSColor*)_blueAlternatingRowColor 
{ 
    return [NSColor redColor]; 
} 

@end 

o para cambiar ambos colores, anular controlAlternatingRowBackgroundColors para devolver una matriz de colores que desea alternado.

@implementation NSColor (ColorChangingFun) 

+(NSArray*)controlAlternatingRowBackgroundColors 
{ 
    return [NSArray arrayWithObjects:[NSColor redColor], [NSColor greenColor], nil]; 
} 

@end 
+1

Por qué truco cuando la API te da una forma? –

+0

um, porque es divertido;) ROFL –

+0

Esto funciona, pero solo cambia uno de los colores. – indragie

4

I subclases NSTableView e implementado drawRow: clipRect: así ...

- (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]; 
} 

Parece que funciona, pero es tan simple que me pregunto si me falta algo.

+3

Desafortunadamente no proporciona colores alternados para filas vacías, solo filas que contienen datos. – Huperniketes

+1

Esto funcionó bien para mí. Puede envolver las primeras tres líneas en un 'if (row! = [Self selectedRow])' para evitar problemas con el fondo resaltado de las filas seleccionadas. – pepsi

+1

@Huperniketes Compruebe [esta pregunta] (http://stackoverflow.com/questions/14178370/draw-nstableview-alternating-rows-like-itunes-11?rq=1) para obtener una solución también para dibujar a medida el fondo de la vista de tabla sin filas – Jay

1

que quería una solución que funcionó al igual que el normal NSTableView, incluido el apoyo para el desplazamiento elástico y tal, así que crearon una subclase NSTableView que tiene un NSColor* propiedad llamada alternateBackgroundColor, y luego hicieron caso omiso del método -drawBackgroundColorInClipRect: así:

- (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

Para que esto funcione, tuve que desactivar usesAlternatingRowBackgroundColors y llevar a cabo la comprobación condicional. De lo contrario, la vista de tabla estaba dibujando sobre la parte superior de esta y solo vi las filas virtuales dibujadas más allá de los límites de la tabla. – greg

3

No estoy seguro de qué tan recientemente se haya agregado esto, o si es tan flexible como lo necesita, pero noté que puede especificar filas "Alternas" en el Creador de interfaces en Xcode 4.6 (y posiblemente antes) .

  1. Abra su plumín en Xcode y seleccione su NSTableView o NSOutlineView
  2. mostrar atributos Inspector en el panel de Servicios Públicos (⎇⌘4)
  3. la casilla de verificación Aviso Highlight Alternating Rows.

enter image description here

+0

Sí, esta es la opción que estaba usando (ha estado disponible por un tiempo). El problema consistía en poder personalizar los colores alternativos, ya que al marcar esa casilla solo se muestran los colores predeterminados del sistema azul claro/blanco. – indragie

0

Nate Thorn 's answer funcionaba perfectamente para mí.

Aquí está, rediseñado para 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 
      } 
     } 
    } 
} 
Cuestiones relacionadas