Re: drawRect runs twice, bounds are changed in between
Re: drawRect runs twice, bounds are changed in between
- Subject: Re: drawRect runs twice, bounds are changed in between
- From: N!K <email@hidden>
- Date: Wed, 14 Jan 2015 20:39:07 -0800
On Jan 13, 2015, at 10:50 PM, Jens Alfke <email@hidden> wrote:
>
>> On Jan 13, 2015, at 9:25 PM, N!K <email@hidden> wrote:
>>
>> A breakpoint at the end of drawRect shows that it runs twice. After the second pass, the view appears, as it should.
>> Between passes, bounds is changed somehow, as shown by NSLog at the start and end of drawRect.
>> Since this will upset code that I will add later, I’d like to stop this.
>
> The view's being resized, probably as part of view layout. Ideally AppKit shouldn't draw the view before it gets to its final size, but maybe this is part of an animation, or maybe it's something that hasn't been optimized 100% in AppKit.
>
> In general, you should not make assumptions about when and how often -drawRect: will be called. That's up to AppKit. Your job is just to draw the view when you’re told to.
OK. Cause is unknown (probably unknowable?) but part of Cocoa. Just because there was only one pass in other projects, I can’t depend on it. drawRect can happen anytime.
>
> You haven't said why the bounds change will upset your code; is the view being changed to the wrong size? That would be an actual problem, but it isn't related to being drawn multiple times. You'd need to look at the view constraints in your window to diagnose that.
>
> —Jens
“Why” takes a little explaining. Thank you for your patience.
I’m trying to learn more about drawing. One stumbling block was getting an NSBezierPath to change size proportional to the window size when the corner is dragged. Per Graham Cox’s suggestion, the view size change can be detected in subsequent passes of drawRect by comparing
ratioX = NSWidth ([_path bounds])/NSWidth(bounds);
ratioY = NSHeight([_path bounds])/NSHeight(bounds);
with their initial values, which were established in the one pass of drawRect before the view appeared.
This worked perfectly. I used the ratios in
-(void)resize{
scaleX = ratioX0/ratioX;
scaleY = ratioY0/ratioY;
NSAffineTransform* tfm = [[NSAffineTransform alloc] init];
[tfm scaleXBy:scaleX yBy:scaleY];
temp = [tfm transformBezierPath:_path];
}
The initial view was correct. Then dragging the window corner induced drawRect’s, which detected the changes and scaled the original _path each time; no cumulative errors. The path size tracked the view size correctly.
Next I wanted to learn how to scale the whole view in a new project, not just the NSBezierPath. I was planning to later include other objects with the NSBezierPath and wanted them to be scaled, too. I used the same initialization and failed because of the bounds change between two passes, which I failed to anticipate. The first pass set the initial values. The second pass detected the change and scaled the view before the view appeared.
-(void)resize{
scaleX = ratioX0/ratioX;
scaleY = ratioY0/ratioY;
NSAffineTransform* tfm = [[NSAffineTransform alloc] init];
[tfm scaleXBy:scaleX yBy:scaleY];
temp = [tfm transformBezierPath:_path];
}
Thus the path in the initial view was quite different from the initial path, and dragging the corner of the window caused wildly incorrect scaling.
My hope was that there might be a way of suppressing the second pass before display of the view. Now I know better and will figure out another way to initialize and track. Thank you for correcting me.
Nick
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden