25 Stimmen

Gitterlinien in NSTableView nur für ausgefüllte Zeilen zeichnen?

Wie kann ich Gitternetzlinien in einer NSTableView nur für Zeilen zeichnen, die ausgefüllt sind? Wenn ich die Gitterstilmaske auf NSTableViewSolidHorizontalGridStyleMask einstelle, werden Gitterlinien für alle Zeilen gezeichnet, unabhängig davon, ob sie ausgefüllt sind oder nicht.

Ich bin auf der Suche nach einem Beispielcode, um dies zu tun.

44voto

Jacob Gorban Punkte 1421

Der folgende Code hat sich für mich bisher am besten bewährt. Fälschen Sie einfach das ursprüngliche Gitter Zeichnung Code nur auf ausgefüllten Zeilen zu zeichnen.

Unterklasse NSTableView, falls erforderlich, und überschreiben Sie drawGridInClipRect:(NSRect)clipRect wie folgt:

- (void)drawGridInClipRect:(NSRect)clipRect
{
    NSRect lastRowRect = [self rectOfRow:[self numberOfRows]-1];
    NSRect myClipRect = NSMakeRect(0, 0, lastRowRect.size.width, NSMaxY(lastRowRect));
    NSRect finalClipRect = NSIntersectionRect(clipRect, myClipRect);
    [super drawGridInClipRect:finalClipRect];
}

20voto

Oskar Punkte 3412

In Swift 3.1 ist das alles, was Sie brauchen:

import Cocoa

class GridClipTableView: NSTableView {

    override func drawGrid(inClipRect clipRect: NSRect) { }

}

2voto

jscs Punkte 63009

Ich denke, Sie müssen die Unterklasse NSTableView und außer Kraft setzen drawRow:clipRect: . Eine andere Möglichkeit wäre das Überschreiben drawGridInClipRect: aber das ist etwas umständlicher, weil Sie die Zeilen manuell heraussuchen müssen.

Das sollte Sie auf den richtigen Weg bringen:

- (void)drawRow:(NSInteger)rowIndex clipRect:(NSRect)clipRect {
    // First do the default drawing
    [super drawRow:rowIndex clipRect:clipRect];

    // Check if there's content in any of the cells in this row
    BOOL doesHaveContent = NO;
    int numCols = [self numberOfColumns];
    int colIndex;
    for( colIndex = 0; colIndex < numCols; colIndex++ ){
        NSCell * cell = [self preparedCellAtColumn:colIndex 
                                               row:rowIndex];
        if( [cell objectValue] != nil ){
            doesHaveContent = YES;
            break;
        }
    }

    if( doesHaveContent ){
        NSRect rowRect = [self rectOfRow:rowIndex];
        NSBezierPath * gridPath = [NSBezierPath bezierPath];
        // Ignoring clipRect because this isn't a lot of drawing
        [gridPath moveToPoint:rowRect.origin];
        [gridPath lineToPoint:NSMakePoint(rowRect.origin.x + rowRect.size.width,
                                          rowRect.origin.y)];
        [gridPath moveToPoint:NSMakePoint(rowRect.origin.x,
                                          rowRect.origin.y + rowRect.size.height)];
        [gridPath lineToPoint:NSMakePoint(rowRect.origin.x + rowRect.size.width,
                                          rowRect.origin.y + rowRect.size.height)];
        [myGridColor set];
        [gridPath stroke];
        // You could also just do:
        // [myGridColor set];
        // [[NSBezierPath bezierPathWithRect:rowRect] stroke];
    }
}

Eine weitere Möglichkeit wäre, eine benutzerdefinierte NSCell Jede Zelle kann einen speziellen Rahmen um sich selbst ziehen, wenn sie einen Inhalt hat. Dies würde jedoch nicht eine Linie über die gesamte Zeile zeichnen, wenn es einige Zellen in der Zeile, die leer waren.

1voto

DarkDust Punkte 87647

Aus irgendeinem Grund hat keine der beiden hier aufgeführten Lösungen bei mir funktioniert. Was ich stattdessen tat, ist:

  1. Unterklasse NSTableView und außer Kraft setzen rectOfColumn: (siehe unten).
  2. Aktivieren Sie die Ebenenunterstützung für die Tabellenansicht, die Clip-Ansicht und die Bildlaufansicht (dies ist erforderlich, damit diese Lösung funktioniert).

In meinen Tests funktionierte dies von macOS 10.9 bis 10.15.

- (NSRect)rectOfColumn:(NSInteger)column
{
    NSRect value = [super rectOfColumn:column];

    NSInteger numberOfRows = [self numberOfRows];
    if (numberOfRows == 0) {
        value.size.height = 0;
    } else {
        NSRect firstRect = [self rectOfRow:0];
        NSRect lastRect = [self rectOfRow:numberOfRows - 1];

        value.size.height = NSMaxY(lastRect) - NSMinY(firstRect);
    }

    return value;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X