NSTableView:如何在选定行之前和之后绘制自定义分隔符

Fra*_*sme 9 cocoa nstableview

这是我的第一个问题,我将尽可能清楚地做到这一点.

我想在基于视图的NSTableView中的选定行上绘制自定义渐变,同时添加细微的凸起效果.为此,我需要为所选行之前和之后的网格线使用较暗的颜色(请参阅此处的示例).我drawSeparatorInRect:NSTableRowView中有overrode方法来绘制所选行的自定义分隔线(使用isSelected方法作为标志),但我不能对上面/下面的那个做同样的事情(因为我在底部/顶部画线).

我已经尝试了几种方法来告诉最近的一行,它应该绘制一个较暗的分隔线而没有成功,因为显示步骤不遵循相同的顺序(我用NSLogs检查了它drawSeparatorInRect:,而且似乎当你滚动一点这个订单变更).因此,有时(主要是在滚动之后)该行不知道它应该使用更暗的颜色,因为它在所选择的之前绘制自己(我想在这一点上,所选行还没有意识到它被选中,否则我不明白发生了什么事.

我试过的一些事情:

  1. drawSeparatorInRect:所选行的方法中,我尝试访问兄弟视图([superview subviews])并强制上一个/下一个再次绘制自己.
  2. NSTableView子类中,在selectedIndexes更改时直接修改最近的行.
  3. 此处drawSeparatorInRect:显示的方法中绘制所选行之外的行.

请注意,我这样做:行查询询问是否选择了上一个/下一个,一个nearestRowIsSelected标志或外部调用方法来"强制"暗色.

我现在所拥有的是所选行绘制了顶部和底部边框,因此其中一个被放置在前一个/下一个行线上......它很微妙但它仍然存在.

任何帮助都会受到好评.

先感谢您.

!我没有发布任何代码,因为问题不存在(它只是[NSBezierPath fillRect:rect]用红色调用),我想...所以我没有任何东西可以显示.

Tim*_*Tim 12

我也试过这个并注意到drawSeparatorInRect:实际上只能绘制它的底部分隔线,因为顶部分隔线的位置(与前一行的底部分隔线相同)是一个像素外(上)行的clipRect.

但是,我通过继承NSTableRowView并使用drawSeparatorInRect来实现它:如下所示:

- (void)drawSeparatorInRect:(NSRect)dirtyRect
{
    // Define our drawing colors
    NSColor *normalColor = [NSColor colorWithCalibratedWhite:0.76 alpha:1.0]; // Default separator color
    NSColor *selectedTopColor = [NSColor colorWithCalibratedWhite:0.60 alpha:1.0]; // Color of the top separator line of selected row
    NSColor *selectedBottomColor = [NSColor colorWithCalibratedWhite:0.60 alpha:1.0]; // Color of the bottom separator line of selected row

    // Define coordinates of separator line
    NSRect drawingRect = [self frame]; // Ignore dirtyRect
    drawingRect.origin.y = drawingRect.size.height - 1.0;
    drawingRect.size.height = 1.0; // Height of the separator line we're going to draw at the bottom of the row

    // Get the table view and info on row index numbers
    NSTableView *tableView = (NSTableView*)[self superview]; // The table view the row is part of
    NSInteger selectedRowNumber = [tableView selectedRow];
    NSInteger ownRowNumber = [tableView rowForView:self];

    // Set the color of the separator line
    [normalColor set]; // Default
    if (([self isSelected]) && ((selectedRowNumber + 1) < [tableView numberOfRows])) [selectedBottomColor set]; // If the row is selected, use selectedBottomColor
    if ((![self isSelected]) && (selectedRowNumber > 0) && (ownRowNumber == (selectedRowNumber-1))) [selectedTopColor set]; // If the row is followed by the selected row, draw its bottom separator line in selectedTopColor

    // Draw separator line
    NSRectFill (drawingRect);

    // If the row is selected, tell the preceding row to redraw its bottom separator line (which is also the top line of the selected row)
    if (([self isSelected]) && (selectedRowNumber > 0)) [tableView setNeedsDisplayInRect:[tableView rectOfRow:selectedRowNumber-1]];
}
Run Code Online (Sandbox Code Playgroud)

此方法将(仅)绘制自己的底部分隔线.如果它是选定的行,它将绘制不使用默认颜色的行,但突出显示,它将告诉前一行重绘其分隔线,即与所选行的顶部分隔线相同.

为了使其工作,一旦选择移动,所选行上方的行需要重绘其底部分隔线.我通过在NST​​ableView委托中使用此方法实现了这一点:

// Tell the row above the row which is going to loose the selection to redraw its bottom separator line
- (BOOL)selectionShouldChangeInTableView:(NSTableView *)aTableView
{
    NSInteger selectedRowNumber = [aTableView selectedRow];
    if (selectedRowNumber > 0) {
    [aTableView setNeedsDisplayInRect:[aTableView rectOfRow:selectedRowNumber-1]];
    }
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

此委托方法告诉仍然选定的行上方的行重绘其分隔线.在选择更改之前立即调用它.