在绘制之前要停止NSView drawRect清除吗? (lockFocus不再在macOS 10.14上运行) [英] Stop NSView drawRect clearing before drawing? (lockFocus no longer working on macOS 10.14)

查看:374
本文介绍了在绘制之前要停止NSView drawRect清除吗? (lockFocus不再在macOS 10.14上运行)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用两个视图的动画,在这里我将调用lockFocus并使用[[NSGraphicsContext currentContext] graphicsPort]进入第二个NSView的图形上下文,然后进行绘制.在macOS 10.14(Mojave)之前,这种方法一直很好.

I have an animation using two views where I would call lockFocus and get at the graphics context of the second NSView with [[NSGraphicsContext currentContext] graphicsPort], and draw. That worked fine until macOS 10.14 (Mojave).

在这里找到了参考: https://developer.apple.com/videos/play/wwdc2018/209/

Found a reference here: https://developer.apple.com/videos/play/wwdc2018/209/

在22:40,他们谈论已经改变的传统"后备商店.上面的lockFocus和上下文模式在屏幕上很大,表示不再起作用.那是真的. lockFocus()仍然有效,甚至可以为您提供正确的NSView,但是通过上下文进行的任何绘制都不再起作用.

At 22:40 they talk about the "legacy" backing store that has changed. The above lockFocus and context pattern was big on the screen, saying that that won't work any more. And that is true. lockFocus() still works, and even gets you the correct NSView, but any drawing via the context does not work any more.

当然,绘制视图的正确方法是通过Nsview的drawRect.因此,我重新安排了一切以实现此目的.可以,但是在调用drawRect之前,drawRect已经为您自动清除了脏"区域.如果您使用setNeedsDisplayInRect:它甚至只会为您清除那些区域.但是,它还将清除由多个脏矩形组成的区域.而且,当我绘制圆形对象时,它会清除矩形区域,因此最终会导致清除过多(黑色区域):

Of course the proper way to draw in a view is via Nsview's drawRect. So I rearranged everything to do just that. That works, but, drawRect has already automatically cleared the "dirty" area for you, prior to calling your drawRect. If you used setNeedsDisplayInRect: it will even clear only those areas for you. But, it will also clear areas made up of more than one dirty rectangle. And, it clears rectangular areas, while I draw roundish objects, so I end up with too much cleared away (black area):

有没有办法防止drawRect清除背景?

Is there a way to prevent drawRect to clear the background?

否则,我将转而使用NSView的图层,并使用updateLayer或其他东西.

If not I will have switch to using the NSView's layer instead, and use updateLayer, or something.

更新:我正在使用NSView层,为wantLayer和wantsUpdateLayer返回TRUE,并实现:

Update: I am playing around with using the layers of NSView, returning TRUE for wantsLayer and wantsUpdateLayer, and implementing:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

在执行操作时仅调用 :

- (BOOL) wantsLayer { return YES; }
- (BOOL) wantsUpdateLayer { return NO; } 

使用setNeedsDisplayInRect:或setNeedsDisplay:

and use setNeedsDisplayInRect: or setNeedsDisplay:

这确实使drawRect不再被调用,但是到我的drawLayer:调用时,已经发生了相同的自动背景擦除.所以我在那里没有任何进展.确实是setNeedsDisplayInRect的效果,而不是我的绘图.仅调用setNeedsDisplayInRect会导致这些擦除.

Which indeed makes drawRect no longer called, but the same automatic background erase has already taken place by the time my drawLayer: is called. So I have not made any progress there. It really is the effect of setNeedsDisplayInRect, and not my drawing. Just calling setNeedsDisplayInRect causes these erases.

如果您设置:

- (BOOL) wantsLayer { return YES; }
- (BOOL) wantsUpdateLayer { return YES; } 

唯一被称为的是:

- (void) updateLayer

这没有为我提供绘图的上下文.

which does not provide me with a context to draw.

我希望:

self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawNever;

NSView文档说:

The NSView doc says:

单独保留图层的内容.切勿将图层标记为需要 显示或将视图的内容绘制到图层.这就是 开发人员创建的图层(图层托管视图)得到处理.

Leave the layer's contents alone. Never mark the layer as needing display, or draw the view's contents to the layer. This is how developer created layers (layer-hosting views) are treated.

它确实做到了.它不会通知您,也不会呼叫代表.

and it does exactly that. It doesn't notify you, or call delegates.

是否可以完全控制NSView/图层的内容?

更新2019年1月27日: 我猜NSView有一个方法makeBackingLayer并非没有.实现了这一点,并且看起来似乎可以正常工作,但是屏幕上没有显示任何输出.因此出现了后续问题: nsview-makebackinglayer-with-calayer-subclass-displays -无输出

UPDATE 2019-JAN-27: NSView has a method makeBackingLayer that is not there for nothing, I guess. Implemented that, and it seems to work, basically, but no output shows on screen. Hence the followup question: nsview-makebackinglayer-with-calayer-subclass-displays-no-output

推荐答案

使用NSView lockFocusunlockFocus,或尝试直接访问窗口的图形内容在macOS 10.14中不再起作用.

Using NSView lockFocus and unlockFocus, or trying to access the window's graphics contents directly not working in macOS 10.14 anymore.

您可以在此上下文中创建NSBitmapImageRep对象并更新图形.

You can create an NSBitmapImageRep object and update drawing in this context.

示例代码:

- (void)drawRect:(NSRect)rect {
    if (self.cachedDrawingRep) {
        [self.cachedDrawingRep drawInRect:self.bounds];
    }
}

- (void)drawOutsideDrawRect {
     NSBitmapImageRep *cmap = self.cachedDrawingRep;
    if (!cmap) {
        cmap = [self bitmapImageRepForCachingDisplayInRect:self.bounds];
        self.cachedDrawingRep = cmap;
    }
    NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:cmap];
    NSAssert(ctx, nil);
    [NSGraphicsContext setCurrentContext:ctx];

    // Draw code here

    self.needsDisplay = YES;
 }

这篇关于在绘制之前要停止NSView drawRect清除吗? (lockFocus不再在macOS 10.14上运行)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆