What's the preferred/recommended way to draw a line in NSView-drawRect: method?
I couldn't found any line drawing primitive in Cocoa at NSView level. The only thing I've been found is NSBezierPath
. Is this a preferred way? Or is there another way开发者_高级运维 which I couldn't discovered?
NSBezierPath
is exactly what you should be using. If you just want to draw a straight line from one point to another, use the class method:
+strokeLineFromPoint:(NSPoint)point1 toPoint:(NSPoint)point2
Cocoa uses an implicit drawing stack, and an invalidation model. In your NSView, when state changes that would cause the view to draw differently, you invoke -[self setNeedsDisplay:] to tell the drawing system that you need to be redrawn. At some point in very near future, actually the end of the current event loop, your view's drawRect: method will be called. That's your opportunity to draw anything you'd like.
There's an implicit focus stack, meaning that when your view's drawRect: is called, drawing is focused on and clipped to the bounds of your view in the window it is in. You can then call functions like [[NSColor redColor] set]; and NSRectFill([self bounds]);
Here's an example:
@interface MyView : NSView {
@private
NSColor *lineColor;
NSInteger clickCount;
}
@end
@implementation MyView
- (void)setLineColor:(NSColor *)color {
if (color != lineColor) {
[lineColor release];
lineColor = [color copy];
[self setNeedsDisplay:YES]; /// We changed what we'd draw, invalidate our drawing.
}
}
- (void)mouseDown:(NSEvent *)mouseDown {
clickCount = (clickCount == 6) ? 0 : (clickCount + 1);
CGFloat hue = clickCount / 6.0;
[self setLineColor:[NSColor colorWithCalibratedHue:hue saturation:1.0 brightness:1.0 alpha:1.0]];
}
- (void)drawRect:(NSRect)dirtyRect {
NSBezierPath *line = [NSBezierPath bezierPath];
[line moveToPoint:NSMakePoint(NSMinX([self bounds]), NSMinY([self bounds]))];
[line lineToPoint:NSMakePoint(NSMaxX([self bounds]), NSMaxY([self bounds]))];
[line setLineWidth:5.0]; /// Make it easy to see
[[self lineColor] set]; /// Make future drawing the color of lineColor.
[line stroke];
}
@end
The view should draw a diagonal line, and each time it is clicked the line should change color.
I tried the example given by Jon and found that i needed to add 2 minor fixes to the code sample above.
- insert an allocator of the NSColor into the init block
- change the second moveToPoint so that it becomes a lineToPoint
Once i fixed this, i found the code snippit very useful. NOTE: you probably need to dealloc the NSColor as well.
@interface PropertyPropagateView : NSView {
@private
NSColor *lineColor;
NSInteger clickCount;
}
@end
@implementation PropertyPropagateView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
lineColor=[NSColor blueColor];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (void)setLineColor:(NSColor *)color {
if (color != lineColor) {
[lineColor release];
lineColor = [color copy];
[self setNeedsDisplay:YES]; /// We changed what we'd draw, invalidate our drawing.
}
}
- (void)mouseDown:(NSEvent *)mouseDown {
clickCount = (clickCount == 6) ? 0 : (clickCount + 1);
CGFloat hue = clickCount / 6.0;
[self setLineColor:[NSColor colorWithCalibratedHue:hue saturation:1.0 brightness:1.0 alpha:1.0]];
}
- (void)drawRect:(NSRect)dirtyRect
{
NSBezierPath *line = [NSBezierPath bezierPath];
[line moveToPoint:NSMakePoint(NSMinX([self bounds]), NSMinY([self bounds]))];
[line lineToPoint:NSMakePoint(NSMaxX([self bounds]), NSMaxY([self bounds]))];
[line setLineWidth:5.0]; /// Make it easy to see
[lineColor set]; /// Make future drawing the color of lineColor.
[line stroke];
}
@end
Just to add some info, I make a habit of making sure the graphics state is saved and restored before and after drawing, to keep things zippy.
- (void)drawRect:(NSRect)dirtyRect {
[[NSGraphicsContext currentContext] saveGraphicsState]
NSBezierPath *line = [NSBezierPath bezierPath];
[line moveToPoint:NSMakePoint(NSMinX([self bounds]), NSMinY([self bounds]))];
[line lineToPoint:NSMakePoint(NSMaxX([self bounds]), NSMaxY([self bounds]))];
[line setLineWidth:5.0]; /// Make it easy to see
[[self lineColor] set]; /// Make future drawing the color of lineColor.
[line stroke];
[[NSGraphicsContext currentContext] restoreGraphicsState]
}
精彩评论