Re: erase then draw image?
Re: erase then draw image?
- Subject: Re: erase then draw image?
- From: Brock Brandenberg <email@hidden>
- Date: Sun, 27 Oct 2002 13:44:07 -0600
Hi Matt.
Finally got a few minutes to sit with the sample code you sent. It's hard to
describe exactly how the drawing hierarchy is breaking, but here is the gist
of what's going on (maybe one of the framework engineers can clarify some
details on the graphics context stack and how it gets interfered with in
cases like this).
Certain methods cause notifications to be sent to other objects, which in
turn react to the notifications and cause other methods to be called. In the
case of the setBoundsRotation: method, it's causing the bounds of your view
to change size, which causes a NSViewBoundsDidChangeNotification to be
posted. This in turn, causes the view hierarchy to go about its merry way,
updating and drawing all of the appropriate objects affected by the changed
bounds of your view.
But in this case, the view hierarchy was already in the middle of an update
because your drawRect: method was being executed. So, doing something that
branches out of the drawRect: method and causes more updates is dramatically
interfering with the normal order of execution of the current view update.
It's not clearly documented, but you just need to make sure that you don't
do anything in a drawRect: method that will cause the code to go branching
off and posting all kinds of other notifications. When this happens, the
order of execution becomes much less clear and apparently the inner workings
of the update mechanism can be corrupted.
The proper way to do what you want is to use a transform in the drawRect:
method to manipulate the coordinate system of the view, not the view itself.
Simply declare a transform, rotate it and concatenate it, and your drawing
will be properly rotated and your drawRect: method will execute cleanly
without interfering with the current update mechanism:
- (void)drawRect:(NSRect)rect
{
NSAffineTransform *drawXform = [NSAffineTransform transform];
[drawXform rotateByDegrees:10];
[drawXform concat];
[image drawAtPoint:NSMakePoint(50,25)
fromRect:NSMakeRect(0,0,[image size].width,[image size].height)
operation:NSCompositeSourceOver fraction:0.2];
}
Hope this helps a little. I wish I could point out exactly what is being
corrupted when the notifications interfere with the update, but I don't know
enough about the inner workings to do so.
Bye.
Brock Brandenberg
>
> You need to make sure that you override the isOpaque: method properly in
>
> your view. This is the source of the problem
>
>
No - I was doing that. And this is otiose in any case, since NO is the
>
default.
>
>
> Another thing to watch out for is overlapping views. If your views are not
>
> completely contained within one another in the coordinate system, the view
>
> hierarchy gets confused and drawing doesn't occur properly
>
>
The watermark view is the same size as the contentview of the window, so
>
overlapping is complete. So I don't think this can be the problem either.
>
>
I think the problem is related to the rotation of the coordinate system, but
>
I'm not sure how.
>
>
I append some sample code. (Remember, I'm no longer using anything like this
>
code, but I'm just curious as to how to fix it to make it work, if this is
>
possible.)
>
>
To see the problem, make a window, put into it a custom NSView the same size
>
as the window, and over that put a button and a couple of non-editable
>
textfields (the watermark must be drawn behind everything, so this layering
>
order is important). If I comment out both line 1 and line 2 the problem does
>
not immediately show itself, but we don't get any rotation either. If I
>
comment out line 2, the textfields are rotated, which is wrong; thus it is
>
important to include line 2. If I include line 1 and line 2, the original
>
problem with darkening of the text appears - press the button several times to
>
see it happen.
>
>
This is the NSView code. image is an NSImage ivar.
>
>
- (id)initWithFrame:(NSRect)frame {
>
self = [super initWithFrame:frame];
>
if (self) {
>
NSString* text = @"HOWDY";
>
NSFont* geneva100 = [NSFont fontWithName: @"Geneva" size: 100];
>
NSColor* blue = [NSColor blueColor];
>
NSDictionary* attrs = [NSDictionary dictionaryWithObjectsAndKeys:
>
geneva100, NSFontAttributeName,
>
blue, NSForegroundColorAttributeName, nil];
>
image = [[[NSImage alloc] init] retain];
>
[image setSize: NSMakeSize(frame.size.width/2, frame.size.height/2)];
>
[image lockFocus];
>
[text drawAtPoint:NSMakePoint(0,0) withAttributes:attrs];
>
[image unlockFocus];
>
}
>
return self;
>
}
>
>
- (BOOL) isOpaque {
>
return NO;
>
}
>
>
- (void)drawRect:(NSRect)rect {
>
[self setBoundsRotation: 10]; // line 1
>
[image drawAtPoint:NSMakePoint(50,25)
>
fromRect:NSMakeRect(0,0,[image size].width,[image size].height)
>
operation:NSCompositeSourceOver fraction:0.2];
>
[self setBoundsRotation: 0]; // line 2
>
}
----- industrial design @ www.bergdesign.com ------
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.