在NSView-drawRect:方法中绘制直线的首选/推荐方法是什么?

时间:2011-05-07 04:20:53

标签: cocoa drawing line nsview

我在NSView级别的Cocoa中找不到任何线条图原语。我找到的唯一一件事是NSBezierPath。这是首选方式吗?还是有另一种我无法发现的方式?

4 个答案:

答案 0 :(得分:14)

NSBezierPath正是您应该使用的。如果您只想从一个点到另一个点绘制直线,请使用类方法:

+strokeLineFromPoint:(NSPoint)point1 toPoint:(NSPoint)point2

答案 1 :(得分:8)

Cocoa使用隐式绘图堆栈和失效模型。在NSView中,当状态更改会导致视图绘制方式不同时,您调用 - [self setNeedsDisplay:]告诉绘图系统您需要重绘。在不久的将来的某个时刻,实际上是当前事件循环的结束,将调用您的视图的drawRect:方法。这是你抽出任何你想要的东西的机会。

有一个隐含的焦点堆栈,这意味着当你的视图的drawRect:被调用时,绘图会聚焦并剪切到你所在窗口中视图的边界。然后你可以调用像[[NSColor redColor] set]这样的函数;和NSRectFill([self bounds]);

以下是一个例子:

@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

视图应绘制一条对角线,每次单击该线条时,该线条应改变颜色。

答案 2 :(得分:2)

我尝试了Jon给出的示例,发现我需要在上面的代码示例中添加2个小修补程序。

  1. 将NSColor的分配器插入init块
  2. 更改第二个moveToPoint,使其成为lineToPoint
  3. 一旦我解决了这个问题,我发现代码snippit非常有用。 注意:您可能还需要释放NSColor。

    @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
    

答案 3 :(得分:1)

只是为了添加一些信息,我养成了确保在绘图前后保存和恢复图形状态的习惯,以保持活力。

- (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]

}