如何在行选择中更改NSTextField文本颜色?

时间:2012-06-29 20:36:37

标签: cocoa nstextfield

对于cocoa,我将 NSTableView 设置为基于视图。选择行后,文本字段会将其颜色更改为白色。我怎么把它保持黑色?

我还应该注意,突出显示被设置为源列表(它在常规上做同样的事情)。 Highlight Setting

未选择的行Unselected

选定的行Selected Row

我希望有类似iOS的状态配置:

enter image description here

这是在WWDC 2011 Session 120中提出的,但它有点延迟,所以我不打算使用它。它可能适用于其他人。

- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
    [tableView enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row){
        NSTableCellView *cellView = [rowView viewAtColumn:0];
        if(rowView.selected){
            cellView.textField.font = [NSFont boldSystemFontOfSize:14];
        }else{
            cellView.textField.font = [NSFont systemFontOfSize:14];
        }
    }];
}

7 个答案:

答案 0 :(得分:16)

根据您需要执行此操作的原因,有两种方法。

您可以继承NSTableRowView并覆盖-[NSTableRowView interiorBackgroundStyle]以返回NSBackgroundStyleLight。这将告诉单元格它们在浅色背景上并绘制黑色文本。

另一种方法是继承NSTableCellView并覆盖-[NSTableCellView setBackgroundStyle:]并自己设置颜色。

答案 1 :(得分:15)

无需自定义代码即可完成此任务。

只需在Interface Builder中将标签的颜色设置为“标签颜色”即可。只有当标签设置了“控制文本颜色”且位于NSTableCellView中时,自动白/黑物才会起作用。

答案 2 :(得分:14)

覆盖NSTableCellView并添加此方法以在选择单元格时更改文本颜色。

- (void) setBackgroundStyle:(NSBackgroundStyle)backgroundStyle
{
    NSTableRowView *row = (NSTableRowView*)self.superview;
    if (row.isSelected) {
        self.textField.textColor = [NSColor blackColor];
    } else {
        self.textField.textColor = [NSColor whiteColor];
    }

}

答案 3 :(得分:2)

我想出了一个不同的解决方案。如果Cocoa支持@IBOutletCollection,则可以对NSTableCellView进行子类化。因为那时我可以有一个Cell子类,其中包含单元格中所有NSTextField的数组。但由于我有多种具有不同数量的NSTextFields的单元格,所以我不喜欢这个选项。相反,我查看了Apple的NSTableCellView中backgroundStyle属性的文档。

  

默认实现自动转发对所有实现setBackgroundStyle的子视图的调用:或者是NSControl,它们具有响应backgroundStyle的NSCell类。

如果我的TextField实现了setBackgroundStyle,那么当单元格选择发生变化时,它们会收到通知。但是,这种背景样式的转发不是递归的。因为我的NSTextFields在NSStackViews中,所以他们没有收到消息。为了解决这个问题,我刚刚编写了一个扩展来在所有NSView上实现setBackgroundStyle。它只是转发消息。最后,我添加了NSTextField的扩展以实现此方法。从这个扩展名,我改变文本颜色并调用super。这个解决方案也很好,因为不需要子类。没有NSTableCellView或NSTextField的子类。

将此功能添加到所有视图和所有NSTextField可能会导致NSTextFields出现问题,这些问题不在NSTableViews中,意外地改变了颜色。但到目前为止,只有我的TableViews / OutlineViews中的那些正在改变颜色,这正是我想要的。如果您看到文本字段改变了您不期望的颜色,您可能希望子类化NSTextField并仅在该子类上实现setBackgroundStyle覆盖,而不是将其添加到所有NSTextFields。

我使用的Swift 3中的代码粘贴在下面。

extension NSView {
    func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
        for view in self.subviews {
            view.setBackgroundStyle(newValue)
        }
    }
}

extension NSTextField {
    override func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
        switch newValue {
        case .dark:
            self.textColor = NSColor.controlLightHighlightColor
        case .light, .lowered, .raised:
            self.textColor = NSColor.labelColor
        }
        super.setBackgroundStyle(newValue)
    }
}

答案 4 :(得分:1)

对于我的Swift应用程序,以上所有内容似乎都没有正常工作。此方法正确处理NSTableView失去焦点,当窗口不是关键窗口但仍然选中单元格时。

NSTableCellView子类中使用以下内容:

override var backgroundStyle: NSView.BackgroundStyle {
  willSet {
    if newValue == .dark {
      title.textColor = NSColor.white
    } else {
      title.textColor = NSColor.labelColor
    }
  }
}

答案 5 :(得分:0)

根据@ sabes的回答,我创建了这个NSTextFieldCell子类,您可以在选择或取消选择行时设置自定义文本颜色。您可以在IB中设置相关文本字段单元的子类。

@interface SNBlueTextFieldCell : NSTextFieldCell

@end

@implementation SNBlueTextFieldCell

- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
    [self setTextColor:(backgroundStyle==NSBackgroundStyleDark ? [NSColor blackColor] : [NSColor blueColor])];
}

@end

答案 6 :(得分:0)

在 macOS 11 或更高版本中,.dark.light 背景样式已弃用。但您可以改用 .emphased

override var backgroundStyle: NSView.BackgroundStyle {
    willSet {
        textField.textColor = newValue == .emphasized ? .labelColor : .secondaryLabelColor
    }
}

在示例中,.labelColor 是选定的颜色,.secondaryLabelColor 是未选定的颜色。