2010-10-20 18 views

risposta

7

Trovato un modo migliore per farlo here. Questo metodo sostituisce il metodo highlightSelectionInClipRect: in una sottoclasse NSTableView in modo da poter utilizzare qualsiasi colore desiderato per le righe alternate. Non è così maniacale come usare una categoria NSColor, e riguarda solo le visualizzazioni delle tabelle che scegli.

+1

+100 Ho incontrato questa domanda alcuni giorni fa sperando in una buona risposta, ma non ne trovai una soddisfacente. Per fortuna, mi è capitato di vederlo venire di nuovo! Grazie! –

+1

Questo non ha funzionato abbastanza per me. Sembra buono a meno che non inizi a scorrere su e giù con la barra di scorrimento. Quindi il re-drawing viene incasinato e si finisce con un sacco di linee orizzontali bianche nelle righe colorate. Ho messo la mia implementazione qui sotto, ma è così semplice che mi chiedo se mi manchi qualcosa. – sam

1

Non esiste alcuna proprietà impostabile per questo, tuttavia è possibile rispondere al metodo delegato -tableView:willDisplayCell:forTableColumn:row: e impostare il colore di sfondo della cella in base all'uguaglianza del numero di riga.

+2

Questo non sembra funzionare quando non ci sono celle della vista tabella (non cambia lo sfondo della vista tabella stessa) – indragie

7

Se si desidera utilizzare un modo non documentato, fare una categoria NSColor e sovrascrivere _blueAlternatingRowColor come questo:

@implementation NSColor (ColorChangingFun) 

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

@end 

o per modificare entrambi i colori, eseguire l'override controlAlternatingRowBackgroundColors per restituire una matrice di colori che si desidera alternati.

@implementation NSColor (ColorChangingFun) 

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

@end 
+1

Perché mod quando l'API ti dà un modo? –

+0

um, perché è divertente;) ROFL –

+0

Funziona, ma cambia solo uno dei colori. – indragie

4

I sottoclasse NSTableView e attuate drawRow: clipRect: in questo modo ...

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

Sembra funzionare, ma è così semplice che mi chiedo se mi manca qualcosa.

+3

Sfortunatamente non fornisce colori alternati per righe vuote, solo righe che contengono dati. – Huperniketes

+1

Questo ha funzionato bene per me. Potresti voler racchiudere le prime tre linee in un 'if (row! = [Self selectedRow])' per evitare problemi con lo sfondo evidenziato delle righe selezionate. – pepsi

+1

@Huperniketes Controlla [questa domanda] (http://stackoverflow.com/questions/14178370/draw-nstableview-alternating-rows-like-itunes-11?rq=1) per una soluzione per disegnare anche lo sfondo della vista della tabella senza righe – Jay

1

volevo una soluzione che ha funzionato proprio come la normale NSTableView, incluso il supporto per lo scorrimento elastico e simili, così ho creato un NSTableView sottoclasse che ha un NSColor* proprietà chiamata alternateBackgroundColor, e quindi escludeva il metodo -drawBackgroundColorInClipRect: in questo modo:

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

Per fare questo lavoro ho dovuto disabilitare usesAlternatingRowBackgroundColors e prendere il check out condizionale. Altrimenti, la vista della tabella stava disegnando sopra e ho visto solo le righe virtuali disegnate oltre i limiti della tabella. – greg

3

non sono sicuro di quanto recentemente è stato aggiunto questo, o se è flessibile come è necessario che sia, ma ho notato che è possibile specificare le righe "alternata" in Interface Builder in Xcode 4.6 (e forse anche prima) .

  1. Aprire il pennino in Xcode e selezionare il NSTableView o NSOutlineView
  2. mostrare gli attributi Ispettore nel riquadro Utilities (⎇⌘4)
  3. Avviso la casella di controllo Highlight Alternating Rows.

enter image description here

+0

Sì, questa è l'opzione che stavo usando (è in circolazione da un po '). Il problema è stato riuscire a personalizzare i colori alternati da quando ticchetti quella casella ti dà solo i colori di sistema luce blu/bianco di default. – indragie

0

s' answerNate Thorn ha funzionato perfettamente per me.

Qui è, refactoring per 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 
      } 
     } 
    } 
} 
Problemi correlati