Reputation: 528
I want to arrange several custom NSViews one after the other. But when I run the App, views are drawn with different (doubled) frame origin values, than are values set in code.
Here is simplified code with 2 views:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
float height1 = 40.0;
float height2 = 65.0;
float width = [[window contentView] frame].size.width;
NSRect r1 = NSMakeRect(0, 0, width, height1);
NSRect r2 = NSMakeRect(0, height1, width, height2);
MyView *c1 = [[MyView alloc] initWithFrame:r1];
MyView *c2 = [[MyView alloc] initWithFrame:r2];
[[window contentView] addSubview:c1];
[[window contentView] addSubview:c2];
}
code for MyView basically consists only from drawRect:
- (void)drawRect:(NSRect)dirtyRect {
// Drawing code here.
NSRect cellFrame = [self frame];
// frame Y coordinates at superview
float superY = [self convertPoint:[self frame].origin
toView:[self superview]].y;
NSLog(@"superY:%f selfY:%f", superY, cellFrame.origin.y);
// top, bottom border and diagonal line of [self frame]
NSBezierPath* borderLine = [NSBezierPath bezierPath];
NSPoint pt1 = NSMakePoint(cellFrame.origin.x,
cellFrame.origin.y);
NSPoint pt2 = NSMakePoint(cellFrame.origin.x + cellFrame.size.width,
cellFrame.origin.y);
NSPoint pt3 = NSMakePoint(cellFrame.origin.x,
cellFrame.origin.y + cellFrame.size.height);
NSPoint pt4 = NSMakePoint(cellFrame.origin.x + cellFrame.size.width,
cellFrame.origin.y + cellFrame.size.height);
[borderLine moveToPoint:pt1];
[borderLine lineToPoint:pt2];
[borderLine lineToPoint:pt3];
[borderLine lineToPoint:pt4];
[[NSColor redColor] setStroke];
[borderLine setLineWidth:01];
[borderLine stroke];
}
and here is the result (as you can see - 'y' coordinate of second view is doubled and for some reason, this view is only partly drawn):
Upvotes: 0
Views: 447
Reputation: 7272
You are mixing up the concept of a view's frame and bounds rectangles. "Bounds" refer's to a view's dimensions in its own coordinate system, i.e. the origin will be zero and the size will be the view's width and height.
"Frame" refers to a view's dimensions in it's parent view's coordinate system, i.e. the origin will be wherever the view is positioned in its superview, and the width and height will be the same as the bounds rectangle's.
So for the logging in your example code, you are calling "convertPoint" unnecesarily and incorrectly, because you can get the view's actual origin simply by calling "[self frame].origin"
When doing drawing, you need to call "[self bounds]" to get the rectangle in which to draw. In your code you are calling "[self frame]" which gives you a rectangle in your superview's coordinate system (frame), but that won't work because the drawing routines draw in the view's own (bounds) coordinate system (i.e. with origin at {0, 0})
An exception to this would be if a view fills the entire content of its superview, in which case you could call either [self bounds] or [self frame], since both would return the same rectangle.
I got your code to work by changing
NSRect cellFrame = [self frame];
to
NSRect cellFrame = [self bounds];
Also, the easiest way to log an NSRect is
NSLog(@"%@", NSStringFromRect([self frame]));
for example.
Hope that helps.
Upvotes: 1