在基于视图的NSTableView上更改选择颜色

时间:2012-02-27 11:00:34

标签: objective-c cocoa osx-lion nstableview

OS X应用程序中的标准突出显示颜色为蓝色。

是否可以将其更改为其他颜色,例如灰色?

请注意,我使用的是从OS X 10.7开始提供的基于视图的新NSTableView

14 个答案:

答案 0 :(得分:74)

由于您正在使用基于视图的NSTableView,因此可以将NSTableRowView子类化,将其提供给表委托方法- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row;,然后在行视图类中自定义您的选择。

以下是一个例子:

- (void)drawSelectionInRect:(NSRect)dirtyRect {
    if (self.selectionHighlightStyle != NSTableViewSelectionHighlightStyleNone) {
        NSRect selectionRect = NSInsetRect(self.bounds, 2.5, 2.5);
        [[NSColor colorWithCalibratedWhite:.65 alpha:1.0] setStroke];
        [[NSColor colorWithCalibratedWhite:.82 alpha:1.0] setFill];
        NSBezierPath *selectionPath = [NSBezierPath bezierPathWithRoundedRect:selectionRect xRadius:6 yRadius:6];
        [selectionPath fill];
        [selectionPath stroke];
    }
}

答案 1 :(得分:13)

这是James Chen在Swift 3中的解决方案。我还添加了委托方法。

class MyNSTableRowView: NSTableRowView {

    override func drawSelection(in dirtyRect: NSRect) {
        if self.selectionHighlightStyle != .none {
            let selectionRect = NSInsetRect(self.bounds, 2.5, 2.5)
            NSColor(calibratedWhite: 0.65, alpha: 1).setStroke()
            NSColor(calibratedWhite: 0.82, alpha: 1).setFill()
            let selectionPath = NSBezierPath.init(roundedRect: selectionRect, xRadius: 6, yRadius: 6)
            selectionPath.fill()
            selectionPath.stroke()
        }
    }
}

NSTableViewDelegate:

func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
    return MyNSTableRowView()
}

答案 2 :(得分:12)

使用以下代码回复NSTableViewDelegate协议tableViewSelectionDidChange

获取所选行的NSTableRowView并在其上调用方法setEmphasized。 当setEmphasized设置为YES时,您将获得蓝色突出显示;如果不是,则获得灰色突出显示。

-(void)tableViewSelectionDidChange:(NSNotification *)aNotification {

     NSInteger selectedRow = [myTableView selectedRow];
     NSTableRowView *myRowView = [myTableView rowViewAtRow:selectedRow makeIfNecessary:NO];
     [myRowView setEmphasized:NO];
}

答案 3 :(得分:6)

Jean-Pierre 的一些修改

使用以下代码响应NSTableViewDelegate协议tableViewSelectionDidChange:

获取所选行的NSTableRowView并在其上调用setEmphasized方法。当setEmphasized设置为YES时,您将获得蓝色突出显示,如果不是,则获得灰色突出显示。

-(void)tableViewSelectionDidChange:(NSNotification *)aNotification {

 NSInteger selectedRow = [myTableView selectedRow];
 NSTableRowView *myRowView = [myTableView rowViewAtRow:selectedRow makeIfNecessary:NO];
[myRowView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleRegular];
[myRowView setEmphasized:NO];
}

为了避免蓝色的跳舞效果,然后灰色设置

[_tableView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];

答案 4 :(得分:3)

我已经混合了之前描述的所有方法,并获得了完全符合我想要的代码。

  • 选择不改变内部文本字段的颜色;
  • 行记住选择和颜色;
  • 出现任何奇怪的外边框和其他残羹剩饭。

    class AudioCellView: NSTableRowView {
    
        override func draw(_ dirtyRect: NSRect) {
            super.draw(dirtyRect)
            self.wantsLayer = true
            self.layer?.backgroundColor = NSColor.white.cgColor
        }
    
        override var isEmphasized: Bool {
            set {}
            get {
                return false
            }
        }
    
        override var selectionHighlightStyle: NSTableView.SelectionHighlightStyle {
            set {}
            get {
                return .regular
            }
        }
    
        override func drawSelection(in dirtyRect: NSRect) {
            if self.selectionHighlightStyle != .none {
                let selectionRect = NSInsetRect(self.bounds, 2.5, 2.5)
                NSColor(calibratedWhite: 0.85, alpha: 0.6).setFill()
                let selectionPath = NSBezierPath.init(rect: selectionRect)
                selectionPath.fill()
            }
        }
    }
    

答案 5 :(得分:2)

使用Swift时,你可以在10.10上为基于视图的单元格

执行此操作

NSTableCellView进行子类化并实现:

//override to change background color on highlight
override var backgroundStyle:NSBackgroundStyle{
    //check value when the style was setted
    didSet{
        //if it is dark the cell is highlighted -> apply the app color to it
        if backgroundStyle == .Dark{
            self.layer!.backgroundColor = yourColor
        }
        //else go back to the standard color
        else{
            self.layer!.backgroundColor = NSColor.clearColor().CGColor
        }
    }
}

请注意,NSTableView突出显示样式必须设置为Regular,如果它在SourceList上,则会导致一些奇怪的剪辑。

这不是最干净的解决方案,但它在优胜美地上运作良好

答案 6 :(得分:1)

在我看来有一个选项可以改变这个coz文档说三个选择样式和常规的默认样式是蓝色,看下面的图像..你需要发送一条消息,我无法弄清楚因为我之前从未开发过mac应用程序..希望这有助于......!

enter image description here

答案 7 :(得分:1)

如前所述,将emphasized属性设置为false,但在自定义NSTableRowView类中执行以避免副作用(如跳舞颜色效果):

    override func drawRect(dirtyRect: NSRect) {
       super.drawRect(dirtyRect)
       self.emphasized = false

    }

答案 8 :(得分:0)

您必须继承NSTableView,并重写以下函数以更改交替颜色。

  • (void) drawRow: (NSInteger) row clipRect: (NSRect) clipRect

  • (void) drawBackgroundInClipRect: (NSRect) clipRect **这个改变主色和备用色**

使用for循环并插入此条件(i % 2 == 0)以检测奇数和偶数行。

答案 9 :(得分:0)

好的,所以我知道它已经有了一个已接受的答案,但对于像我这样使用NSOutlineView并且.selectionHighlightStyle = .sourceList的人来说,可以使用此代码将选择设置为灰色。更改选择时此方法不会闪烁,如果应用程序最小化,此方法也将保持灰色。

NSTableView / NSOutlineView委托:

func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView?
{
     let row : CustomRowView = CustomRowView.init()
     row.identifier = "row"

     return row
}

然后用以下内容创建一个新的CustomRowView.swift文件:

class CustomRowView : NSTableRowView
{
    override var isEmphasized: Bool {
        get { return self.isEmphasized }
        set(isEmp) { self.isEmphasized = false }
    }
}

这将始终保持选择灰色。

答案 10 :(得分:0)

在 IB 中也找不到这个。上面的答案告诉您在 tableview delegate tableViewSelectionDidChange: 中设置它可以工作,但缺点是当您选择行时,您 (I) 仍然会在选择时看到短暂的蓝色闪烁。 >

我在数据源中设置了setEmphasized:NO:tableView:viewForTableColumn:row:

clarity_collapsed

因此在进行任何选择之前应用此设置,并且蓝色永远不会出现。对于这个问题,子类化似乎是最重要的。

EDIT1:如果您在表格中滚动并单击,或者转到另一个应用程序并返回,则蓝色选择返回,因此我的建议是执行 [rowView setEmphasized:NO]; 委托数据源中的过程。短暂的蓝色闪烁仍然时不时发生。 (macOS 10.15.7 Catalina)

EDIT2:View based NSTableView selection highlighting 建议添加:

NSTableRowView *rowView = [tableView rowViewAtRow:row makeIfNecessary:YES];
[rowView setEmphasized:NO];

这似乎完全摆脱了蓝色选择,即使没有摆弄 setEmphasized!

EDIT 3(final):毕竟你可以在 IB 中设置它,它是设置“突出显示”,在“样式”下,在“交替行”复选框上方。设置为“无”,等等。

enter image description here

答案 11 :(得分:-2)

这是Jean-Pierre在Swift3中的回答:

func tableViewSelectionDidChange(_ notification: Notification)
    { 
        index = tableView.selectedRow
        let rowView = tableView.rowView(atRow: index, makeIfNecessary: false)
        rowView?.isEmphasized = false
...

它有上面列出的两个限制 - 第一次点击不起作用,第二次点击确实无效。并且,有一种“舞蹈效果”。我不介意第一个,实际上就像第二个。

答案 12 :(得分:-3)

- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
    [tblCategory enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row){
        CustomMainCell *cellView = [rowView viewAtColumn:0];
        if(rowView.selected){
            cellView.txtFieldTitle.textColor=[NSColor colorWithCalibratedRed:245.0/255.0 green:110.0/255.0 blue:65.0/255.0 alpha:1.0];
        }else{
            cellView.txtFieldTitle.textColor=[NSColor whiteColor];
        }
    }];
}

[tblCategory setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];

答案 13 :(得分:-3)

  Use this Notification for NSTableView:

          - (void)tableViewSelectionDidChange:(NSNotification *)notification
            {

                 //You Logic stuff
             }