Layer-Backed NSControl 仍然调用 NSCell 绘图例程

Posted

技术标签:

【中文标题】Layer-Backed NSControl 仍然调用 NSCell 绘图例程【英文标题】:Layer-Backed NSControl Still Calls NSCell Drawing Routines 【发布时间】:2018-06-11 17:53:38 【问题描述】:

上下文:

Apple 在 macOS 上有“软弃用”的 NSCell。我试图减少在我的自定义 NSControl 子类中使用它,而是使用 CALayers 来处理我的绘图。为此,我让我的 NSButton 子类支持图层:

self.wantsLayer = YES;

然后我尝试使用“updateLayer”路径而不是“drawRect”来处理我的绘图:

- (BOOL) wantsUpdateLayer 
    return YES;


- (void) updateLayer  
     // Change layer background/border colors if pressed, disabled, etc.
     // Change text color of a CATextLayer sublayer for button's title. 


问题:

如果我使用-updateLayer,NSCell 仍会接收绘图命令并绘制其标题,从而在我的控件中产生一个“模糊”的标题字符串,因为该字符串被绘制了两次——一次在我的 textLayer 中,一次在 Cell 中。

但是,如果我在-drawRect: 而不是-updateLayer 中执行与上述完全相同的工作,那么单元格不会进行任何绘图(因为我不会使用[self.cell drawInteriorWithFrame:ControlView:] 调用它)

在我的一生中,当关联的 controlView(我的按钮子类)选择使用 -updateLayer 而不是 -drawRect: 时,我无法弄清楚是什么触发了单元格绘图。

我查看了 NSControl.h 和 NSView.h 上的所有方法。我已经覆盖了所有 -updateCell 和相关的方法。这些都不是罪魁祸首。我不能简单地设置self.cell=nil,因为 NSControl 仍然依赖 NSCell 进行事件处理等。

当 NSCell 关联的 controlView 使用 -updateLayer 而不是 -drawRect: 时,谁能告诉我如何阻止 NSCell 绘制?

【问题讨论】:

-[NSButtonCell layoutLayerWithFrame:inView:] 中,单元格添加NSTextField 以绘制标题。覆盖 titleRectForBounds: 并返回 NSZeroRect 以删除标题。 确实有效。将其移至官方答案,我会将其标记为已接受。谢谢! 【参考方案1】:

-[NSButtonCell layoutLayerWithFrame:inView:] 中,单元格添加NSTextField 以绘制标题。覆盖 titleRectForBounds: 并返回 NSZeroRect 以删除标题。

【讨论】:

以上是关于Layer-Backed NSControl 仍然调用 NSCell 绘图例程的主要内容,如果未能解决你的问题,请参考以下文章

在 Layer-Backed 视图上使用核心动画

NSControl 和 NSCell:以正确的方式管理单元状态

NSCell 和 NSControl 之间的关系/区别是啥?

如何使用 NSControl 的编辑(withFrame:editor:delegate:event:)?

OS X 10.10中的自定义NSControl类

NSControl 的 setCellClass 在 OS X 10.10 中已弃用,有啥替代方法可以覆盖 NSTextField 的单元格类?