无需使用draw_ updateRect:NSRect函数即可直接在NSView中绘图

问题描述

我想将CGImage图片直接绘制到View,并且使用绘制功能以常规方法在新Mac Book Pro上每秒只能获得7张图片。因此,我决定改用updateLayer函数。我已经定义了wantUpdateLayer = true,并且按预期方式调用了新的updateLayer函数。但是,这开始了我的问题。使用绘制函数时,我使用“ NSGraphicsContext.current?.cgContext”获得当前的CGContext,但在我的updateLayer函数中,“ NSGraphicsContext.current?.cgContext”为零。因此,我不知道将CGImage放在哪里,它将显示在我的屏幕上。同样,“ self.view?.window?.graphicsContext?.cgContext”和“ self.window?.graphicsContext?.cgContext”也为零。此视图中没有按钮或其他元素,并且在视图的窗口中,只有一张图片填充了整个窗口。并且此图片必须在一秒钟内更改30次。生成图片是由单独的线程完成的,一张图片大约需要1毫秒。我认为无法从NSView类的“外部”编写图片,但是我的updateLayer函数位于该类的内部。

这实际上是函数的外观:

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标志后,在自动调用该函数时,所有三个上下文均为零。

有什么想法在哪里绘制我的CGImage?

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 wanttUpdateLayer返回true,就使用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。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...