platlas
platlas

Reputation: 528

Wrong positioning of subviews

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):

result with console

Upvotes: 0

Views: 447

Answers (1)

Francis McGrew
Francis McGrew

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

Related Questions