Re: Hillegass, Third Edition, Chapter 18
Re: Hillegass, Third Edition, Chapter 18
- Subject: Re: Hillegass, Third Edition, Chapter 18
- From: Antonio Nunes <email@hidden>
- Date: Tue, 15 Jul 2008 09:00:54 +0100
On 15 Jul 2008, at 04:53, Jon Buys wrote:
I'm working through the challenge app at the end of Chapter 18 of
Cocoa
Programming, Third Edition. I've got my app to the point where it
can draw
ovals, but each time I click in the window it seems like the view
redraws
itself. I'm sure that this is a very simple question with a very
simple
answer, but I'm stuck. I've been looking at it for three days now,
and I
think its time to let another set of eyes look at it.
You're constantly asking the whole view to redraw using
setNeedsDisplay:. You only want to redraw the section of the screen
that actually needs to be redrawn. I.e: you want to erase the portion
that encompasses the previous bounds of the path, and draw only the
portion the encompasses the new bounds of the path. For this there is
setNeedsDisplayInRect:, plus you need to actually use the rect that is
passed to you in the drawRect: method, instead of the view's bounds,
since that tells you exactly what part of the view needs updating.
The following code solves the issue of updating only the required
area. It does not solve drawing a new rect on every mouseDown while
maintaining the previously drawn rects. That remains for you as an
exercise.
Note that there are still problems with this implementation:
1. Copy the code as is and run it. Drag an oval around on the canvas:
you'll see the problem soon enough. Think about possible causes for
this. Then comment out the first line in the updateWithOldRect:
method, and uncomment its second line. Then try again. Make sure you
understand why the second line solves the issue.
2. Afer step 1, if you drag an oval around long enough, you will find
that in 2 edge cases some ghosting still occurs. This one I'll leave
you to figure out on your own, other than stating that the cause
involves NSUnionRect and the result of the ANRectFromPoints function,
and that reading the documentation on NSUnionRect should give you a
good hint as to the cause of the issue and how to solve it.
Have fun,
António
==== Header
@interface MyView : NSView {
NSRect currentRect;
NSPoint downPoint;
}
@end
NSRect ANRectFromPoints(NSPoint p1, NSPoint p2); // Given two
corners, make an NSRect.
==== Footer ;-)
@implementation MyView
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
rects = [[NSMutableArray alloc] init];
}
return self;
}
- (void)drawRect:(NSRect)rect {
[[NSColor blackColor] set];
[NSBezierPath fillRect:rect];
[[NSColor whiteColor] set];
[[NSBezierPath bezierPathWithOvalInRect:currentRect] stroke];
}
- (void)updateWithOldRect:(NSRect)oldRect
{
[self setNeedsDisplayInRect:NSUnionRect(oldRect, currentRect)];
//[self setNeedsDisplayInRect:NSInsetRect(NSUnionRect(oldRect,
currentRect), -1, -1)];
}
- (void)mouseDown:(NSEvent *)event
{
NSRect oldRect = currentRect;
downPoint = [self convertPoint:[event locationInWindow] fromView:nil];
currentRect = ANRectFromPoints(downPoint, downPoint);
[self updateWithOldRect:oldRect];
}
- (void)mouseDragged:(NSEvent *)event
{
NSRect oldRect = currentRect;
currentRect = ANRectFromPoints(downPoint, [self convertPoint:[event
locationInWindow] fromView:nil]);
[self updateWithOldRect:oldRect];
}
- (void)mouseUp:(NSEvent *)event
{
NSRect oldRect = currentRect;
currentRect = ANRectFromPoints(downPoint, [self convertPoint:[event
locationInWindow] fromView:nil]);
[self updateWithOldRect:oldRect];
}
@end
inline NSRect ANRectFromPoints(NSPoint p1, NSPoint p2)
{ // Given two corners, make an NSRect.
return NSMakeRect(MIN(p1.x, p2.x), MIN(p1.y, p2.y),
fabs(p1.x - p2.x), fabs(p1.y - p2.y));
}
----------------------------------------------------
There is a world of difference between
searching for happiness and choosing
to be happy.
----------------------------------------------------
_______________________________________________
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