Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 484
eonil Avatar asked May 07 '11 04:05

eonil


People also ask

How to draw a straight line in AutoCAD?

In the “Insert” drop-down menu, select the “Drawing” option. Then press “New”. In the new window, click on the Line tool. After that left-click the mouse and move the cursor to draw a line. Bonus tip: if you want a straight vertical or horizontal line, press and hold the “Shift” button while drawing.

Which function is used to draw a line from a point?

Explanation : The header file graphics.h contains line () function which is described below : line function is used to draw a line from a point (x1,y1) to point (x2,y2) i.e. (x1,y1) and (x2,y2) are end points of the line.The code given below draws a line.

How to draw a line from a point in C++?

line function is used to draw a line from a point(x1,y1) to point(x2,y2) i.e. (x1,y1) and (x2,y2) are end points of the line.The code given below draws a line. // C++ Implementation for drawing line.

How to draw a line in Photoshop?

The simplest method for drawing a line in Photoshop is using the Line tool (*gasp*). This tool allows you to create a single straight line segment between two points, but that’s it! No fancy bells and whistles. If you want to draw a more complex line, check out the next method!


3 Answers

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

like image 178
Rob Keniger Avatar answered Jun 21 '23 20:06

Rob Keniger


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.

like image 27
Jon Hess Avatar answered Jun 21 '23 18:06

Jon Hess


I tried the example given by Jon and found that i needed to add 2 minor fixes to the code sample above.

  1. insert an allocator of the NSColor into the init block
  2. 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
like image 28
Ben Avatar answered Jun 21 '23 18:06

Ben