不使用 draw(_ updateRect: NSRect) 函数直接在 NSView 中绘图
Drawing directly in a NSView without using the draw(_ updateRect: NSRect) function
我想将 CGImage 图片直接绘制到 View 中,使用绘图函数的常规方法我在新的 Mac Book Pro 上每秒只能获得 7 张图片。所以我决定改用 updateLayer 函数。我已经定义了 wantsUpdateLayer = true 并且我的新 updateLayer 函数被按预期调用。但随后开始了我的问题。使用 draw func 时,我使用“NSGraphicsContext.current?.cgContext”获取当前 CGContext,但在我的 updateLayer func 中,“NSGraphicsContext.current?.cgContext”为 nil。所以我不知道把我的 CGImage 放在哪里,它会显示在我的屏幕上。此外,“self.view?.window?.graphicsContext?.cgContext”和“self.window?.graphicsContext?.cgContext”也为零。此视图中没有按钮或其他元素,在视图的 window 中,只有一张图片,填满了完整的 window。而这张图,一秒钟要变30次。生成图片由一个单独的线程完成,一张图片大约需要 1 毫秒。我认为从 NSView class 的“外部”无法写出图片,但我的 updateLayer 函数在 class.
内部
下面是 func 的实际样子:
override func updateLayer ()
{
let updateRect: NSRect = NSRect(x: 0.0, y: 0.0, width: 1120.0, height: 768.0)
let context1 = self.view?.window?.graphicsContext?.cgContext
let context2 = self.window?.graphicsContext?.cgContext
let context3 = NSGraphicsContext.current?.cgContext
}
并且在我设置needsDisplay标志后自动调用该函数时,所有三个上下文都为nil。
知道在哪里绘制我的 CGImages 吗?
updateLayer 函数由用户界面自动调用。我不手动调用它。它由视图调用。我的问题是在这个方法中将我的图片显示在屏幕上的位置。也许我必须添加一个图层或使用视图的默认图层,但我不知道该怎么做。
与此同时,我从一个好朋友那里找到了解决方案:
override var wantsUpdateLayer: Bool
{
return (true)
}
override func updateLayer ()
{
let cgimage: CGImage? = picture // Here comes the picture
if cgimage != nil
{
let nsimage: NSImage? = NSImage(cgImage: cgimage!, size: NSZeroSize)
if nsimage != nil
{
let desiredScaleFactor: CGFloat? = self.window?.backingScaleFactor
if desiredScaleFactor != nil
{
let actualScaleFactor: CGFloat? = nsimage!.recommendedLayerContentsScale(desiredScaleFactor!)
if actualScaleFactor != nil
{
self.layer!.contents = nsimage!.layerContents(forContentsScale: actualScaleFactor!)
self.layer!.contentsScale = actualScaleFactor!
}
}
}
}
}
这是直接写入图层的方式。根据格式(CGImage 或 NSImage),您首先必须转换它。一旦 func wantsUpdateLayer returns 为真,就会使用 func updateLayer() 而不是 func draw()。就这些了。
所有想看我的“普通”绘图功能的人:
override func draw (_ updateRect: NSRect)
{
let cgimage: CGImage? = picture // Here comes the picture
if cgimage != nil
{
if #available(macOS 10.10, *)
{
NSGraphicsContext.current?.cgContext.draw(cgimage!, in: updateRect)
}
}
else
{
super.draw(updateRect)
}
}
额外的速度是 2 倍或更多,具体取决于您使用的硬件。在现代的 Mac Pro 上,速度只有一点点,但在现代的 Mac Book Pro 上,您将获得 10 倍或更多的速度。这适用于 Mojave 10.14.6 和 Catalina 10.15.6。我没有用旧的 macOS 版本测试它。 “普通”绘图功能适用于 10.10.6 至 10.15.6。
我想将 CGImage 图片直接绘制到 View 中,使用绘图函数的常规方法我在新的 Mac Book Pro 上每秒只能获得 7 张图片。所以我决定改用 updateLayer 函数。我已经定义了 wantsUpdateLayer = true 并且我的新 updateLayer 函数被按预期调用。但随后开始了我的问题。使用 draw func 时,我使用“NSGraphicsContext.current?.cgContext”获取当前 CGContext,但在我的 updateLayer func 中,“NSGraphicsContext.current?.cgContext”为 nil。所以我不知道把我的 CGImage 放在哪里,它会显示在我的屏幕上。此外,“self.view?.window?.graphicsContext?.cgContext”和“self.window?.graphicsContext?.cgContext”也为零。此视图中没有按钮或其他元素,在视图的 window 中,只有一张图片,填满了完整的 window。而这张图,一秒钟要变30次。生成图片由一个单独的线程完成,一张图片大约需要 1 毫秒。我认为从 NSView class 的“外部”无法写出图片,但我的 updateLayer 函数在 class.
内部下面是 func 的实际样子:
override func updateLayer ()
{
let updateRect: NSRect = NSRect(x: 0.0, y: 0.0, width: 1120.0, height: 768.0)
let context1 = self.view?.window?.graphicsContext?.cgContext
let context2 = self.window?.graphicsContext?.cgContext
let context3 = NSGraphicsContext.current?.cgContext
}
并且在我设置needsDisplay标志后自动调用该函数时,所有三个上下文都为nil。
知道在哪里绘制我的 CGImages 吗?
updateLayer 函数由用户界面自动调用。我不手动调用它。它由视图调用。我的问题是在这个方法中将我的图片显示在屏幕上的位置。也许我必须添加一个图层或使用视图的默认图层,但我不知道该怎么做。
与此同时,我从一个好朋友那里找到了解决方案:
override var wantsUpdateLayer: Bool
{
return (true)
}
override func updateLayer ()
{
let cgimage: CGImage? = picture // Here comes the picture
if cgimage != nil
{
let nsimage: NSImage? = NSImage(cgImage: cgimage!, size: NSZeroSize)
if nsimage != nil
{
let desiredScaleFactor: CGFloat? = self.window?.backingScaleFactor
if desiredScaleFactor != nil
{
let actualScaleFactor: CGFloat? = nsimage!.recommendedLayerContentsScale(desiredScaleFactor!)
if actualScaleFactor != nil
{
self.layer!.contents = nsimage!.layerContents(forContentsScale: actualScaleFactor!)
self.layer!.contentsScale = actualScaleFactor!
}
}
}
}
}
这是直接写入图层的方式。根据格式(CGImage 或 NSImage),您首先必须转换它。一旦 func wantsUpdateLayer returns 为真,就会使用 func updateLayer() 而不是 func draw()。就这些了。
所有想看我的“普通”绘图功能的人:
override func draw (_ updateRect: NSRect)
{
let cgimage: CGImage? = picture // Here comes the picture
if cgimage != nil
{
if #available(macOS 10.10, *)
{
NSGraphicsContext.current?.cgContext.draw(cgimage!, in: updateRect)
}
}
else
{
super.draw(updateRect)
}
}
额外的速度是 2 倍或更多,具体取决于您使用的硬件。在现代的 Mac Pro 上,速度只有一点点,但在现代的 Mac Book Pro 上,您将获得 10 倍或更多的速度。这适用于 Mojave 10.14.6 和 Catalina 10.15.6。我没有用旧的 macOS 版本测试它。 “普通”绘图功能适用于 10.10.6 至 10.15.6。