NSTableView单元格显示问题

时间:2012-01-03 15:40:18

标签: objective-c nstableview

我正在使用基于视图的NSTableView,我遇到了一个小问题。

我正在尝试在突出显示时将两个标签的文字颜色从黑色切换为白色。

为此,我编写了以下代码,

- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
    NSView * viewInQuestion = [table viewAtColumn:0 row:[table selectedRow] makeIfNecessary:YES];

    if ([viewInQuestion isNotEqualTo:lastViewSelected])
    {
        [(NSTextField*)lastViewSelected.subviews.lastObject setTextColor:NSColor.blackColor];
        [(NSTextField*)[lastViewSelected.subviews objectAtIndex:1] setTextColor:NSColor.grayColor];
    }

    [(NSTextField*)viewInQuestion.subviews.lastObject setTextColor:NSColor.whiteColor];
    [(NSTextField*)[viewInQuestion.subviews objectAtIndex:1] setTextColor:NSColor.whiteColor];

    lastViewSelected = viewInQuestion;
}

这很有效;我得到了这个结果:

问题在于,即使NSLog告诉我NSTextField的颜色是NSCalibratedWhite(或其他任何名称),有时文本也不会显示为白色。

当textField不可见时(滚动远离它然后返回),颜色也会切换回黑色。然而,即使这样做,NSTextField的颜色仍然记录为白色。

2 个答案:

答案 0 :(得分:1)

在NSTableViewCell上覆盖setBackgroundStyle非常适合我,至少在OS X 10.8上。 (考虑到SO上的相关问题的数量,人们可以猜测之前曾经存在一些问题。)

背景样式在选择事件和窗口激活/停用时更新,就像人们期望的那样。

这是我的自定义单元格impl - 尽可能简单:

@implementation RuntimeInstanceCellView

- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
    [super setBackgroundStyle:backgroundStyle];
    self.detailTextField.textColor = (backgroundStyle == NSBackgroundStyleLight ? [NSColor darkGrayColor] : [NSColor colorWithCalibratedWhite:0.85 alpha:1.0]);
//    self.detailTextField.textColor = (backgroundStyle == NSBackgroundStyleLight ? [NSColor blackColor] : [NSColor whiteColor]);
}

@end

答案 1 :(得分:0)

我的方法非常hacky,可能不是最佳解决方案;但它解决了它,所以这很好。

假设你按照我的方式实现了tableSelectionDidChange,你需要做的就是注册一个NSNotification并实现一个更明确的自定义方法。

在init,awake或didFinishLaunching应用程序的一部分......

NSView * contentView = table.enclosingScrollView.contentView;
[contentView setPostsFrameChangedNotifications:YES];
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(boundsDidChange:) name:NSViewBoundsDidChangeNotification object:contentView];

该计划的其他地方......

(假设hasUpdatedCell是BOOLEAN属性)

- (void)boundsDidChange:(NSNotification *)notification
{
    /* Bounds can change while nothing is selected--> but we only want to execute the method if a cell is selected. */ 

    if ([table selectedRow] == -1) {return;}

    NSRect visibleRect = table.enclosingScrollView.visibleRect;
    NSView * viewInQuestion = [table viewAtColumn:0 row:[table selectedRow] makeIfNecessary:YES];
    NSPoint selectedViewOrigin = [viewInQuestion convertPoint:viewInQuestion.frame.origin toView:table.enclosingScrollView];

    /* If the selected cell is visible, then we can go ahead and redraw the white text as a part of the workaround.
       This is because scrolling away from the selected cell and back will make the cell revert back to black. */

    BOOL cellVisible = NSPointInRect(selectedViewOrigin, visibleRect);

    /* We already know we need to update it, and we will so we don't need to evaluate the next step in the program */

    if (!cellVisible && !hasUpdatedCell) {return;}


    if (cellVisible && !hasUpdatedCell)
    {
        /* The cell is visible but we haven't updated. Let's do it then. */

        [self tableViewSelectionDidChange:nil];
        hasUpdatedCell = YES;
    } 
    else if (!cellVisible)
    {
        /* The cell is not visible and we need to update next time. */

        hasUpdatedCell = NO;
    }
}

然后事情应该正确显示。