Quartz——有时它从空白视图开始,有时则不是

发布于 2024-09-07 21:21:48 字数 1623 浏览 1 评论 0原文

我面前有两个 Quartz iPhone 应用程序。在每个视图中,调用 setNeedsDisplay 都会导致视图重绘自身。但有一个重要的区别。在一种情况下(Mark/Lamarche 书籍“Beginning iPhonedevelopment”中的“Quartz Fun”应用程序),视图每次都以空白开始。在另一种情况下(我正在开发的应用程序),视图从之前存在的任何内容开始,并在其之上添加新的图形。

我不明白这是为什么。有人可以告诉我吗?

谢谢。

编辑#2:我仍然不明白这里发生了什么。但我发现我可以通过调用

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, self.frame);

编辑#3来清除我的视图:显示缩短的代码:

根据评论者的建议,我已经编辑了我的应用程序,以便用很少的代码就出现问题。 [问题的形式现在有点不同,如下所述。]

应用程序委托:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    DiceView *dv = [[DiceView alloc]initWithFrame: window.frame];
    [window addSubview:dv];

    [dv release];
    [window makeKeyAndVisible];
    return YES;

}

DiceView:

- (void)drawRect:(CGRect)rect {
    static int nDrawrectCalls = 0;
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 1.0);
    CGContextSetStrokeColorWithColor(context, (nDrawrectCalls%5==0?[UIColor redColor]:[UIColor greenColor]).CGColor);
    CGContextMoveToPoint(context, 10, 30+10*nDrawrectCalls);
    CGContextAddLineToPoint(context, 300, 30+10*nDrawrectCalls);
    CGContextStrokePath(context);
    nDrawrectCalls++;
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    [self setNeedsDisplay];
}

其他一切都只是默认的存根方法。

现在来说说区别。现在,它似乎开始使用两次触摸之前屏幕上的任何内容进行绘制。换句话说,在触摸 #2 后,我看到了初始线,加上触摸 #2 的线,但看不到触摸 #1 的线。在触摸 #3 后,我看到触摸 #1 和 #3 的线条。在触摸 #4 后,我看到了初始行以及触摸 #2 和 #4 的行。等等。

I have in front of me two Quartz iPhone apps. In each of them, calls to setNeedsDisplay cause a view to redraw itself. But there is an important difference. In one case (the "Quartz Fun" app from the Mark/Lamarche book "Beginning iPhone development"), the view starts out blank each time. In the other case (the app I am working on), the view starts with whatever was there before, and new graphics are added on top of it.

I can't figure out why this is. Can anyone clue me in?

Thanks.

EDIT #2: I still don't understand what is going on here. But I have figured out that I can clear my view by calling

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, self.frame);

EDIT #3: showing shortened code:

As a suggested by a commenter, I have edited my app so that the issue occurs with very little code. [The form of the issue is a bit different now, as explained below.]

App delegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    DiceView *dv = [[DiceView alloc]initWithFrame: window.frame];
    [window addSubview:dv];

    [dv release];
    [window makeKeyAndVisible];
    return YES;

}

DiceView:

- (void)drawRect:(CGRect)rect {
    static int nDrawrectCalls = 0;
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 1.0);
    CGContextSetStrokeColorWithColor(context, (nDrawrectCalls%5==0?[UIColor redColor]:[UIColor greenColor]).CGColor);
    CGContextMoveToPoint(context, 10, 30+10*nDrawrectCalls);
    CGContextAddLineToPoint(context, 300, 30+10*nDrawrectCalls);
    CGContextStrokePath(context);
    nDrawrectCalls++;
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    [self setNeedsDisplay];
}

Everything else is just default stub methods.

Now for the difference. It now appears to start drawing with whatever was on the screen two touches prior. In other words, after touch #2, I see the initial line, plus the line from touch #2 -- but not the line from touch #1. After touch #3, I see the lines from touches #1 and #3. After touch #4, I see the initial line and the lines from touches #2 and #4. And so on.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧时浪漫 2024-09-14 21:21:48

UIView 有一个 clearsContextBeforeDrawing 布尔属性,可以在您描述的不同行为之间切换。默认值为 YES,这意味着视图在调用 DrawRect: 之前清空上下文:

检查该属性是否在示例中的某处设置。

显然,当视图上没有设置背景颜色时,视图无法正确清除其上下文。请将背景颜色设置为 nil 以外的值。

我认为这是一个错误,并已提交 rdar://8165730


编辑

这不是一个错误。您必须将不透明属性设置为“NO”或“backgroundColor”。 UIView 文档中描述了该行为。

属性clearsContextBeforeDrawing

该属性的默认值为
是的。当设置为 YES 时,当前
图形上下文缓冲区中
drawRect: 方法是自动的
之前清除为透明黑色
绘制矩形:被调用。如果视图的
opaque 属性也设置为 YES,
的背景颜色属性
view 不能为 nil 或绘图错误
可能会发生。

如果该属性的值为NO,
视图的责任是
完全填满其内容。绘画
如果这样做的话,性能可以得到提高
属性为“否”——例如,当
滚动。

属性不透明

是,如果它是不透明的;否则,不。如果
不透明,绘图操作假设
视图填充其边界并且可以
绘制更高效。结果是
如果不透明且视图不可预测
没有填补它的界限。设置这个
如果视图是完整的或则属性为 NO
部分透明。默认
值为“是”。

UIView has a clearsContextBeforeDrawing boolean property that switches between the different behaviors you describe. The default is YES which means the view empties the context before calling drawRect:

Check if that property is set somewhere in the example.

Apparently a view doesn't clear it's context correctly, when no backgroundColor is set on the view. Please set backgroundColor to something other than nil.

I think this is a bug and have filed rdar://8165730.


EDIT

It's not a bug. You have to set the opaque property to NO or the backgroundColor. The behavior is described in the UIView Documentation.

Property clearsContextBeforeDrawing:

The default value of this property is
YES. When set to YES, the current
graphics context buffer in the
drawRect: method is automatically
cleared to transparent black before
drawRect: is invoked. If the view’s
opaque property is also set to YES,
the backgroundColor property of the
view must not be nil or drawing errors
may occur.

If the value of this property is NO,
it is the view’s responsibility to
completely fill its content. Drawing
performance can be improved if this
property is NO—for example, when
scrolling.

Property opaque:

YES if it is opaque; otherwise, NO. If
opaque, the drawing operation assumes
that the view fills its bounds and can
draw more efficiently. The results are
unpredictable if opaque and the view
doesn’t fill its bounds. Set this
property to NO if the view is fully or
partially transparent. The default
value is YES.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文