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

10

在Cocoa的NSView层级中,我找不到任何线条绘制原语。唯一找到的是NSBezierPath。这是首选的方法吗?还是有其他我未发现的方法?

4个回答

14

NSBezierPath 是你应该使用的类。如果你只想从一个点到另一个点画一条直线,可以使用该类方法:

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


9
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

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

darRect方法中的第二个moveToPoint调用应该是lineToPoint调用。 - Jason Fuerstenberg

2

我尝试了Jon提供的示例,发现需要对上面的代码示例进行2个小修复。

  1. 在init块中插入NSColor的分配器
  2. 将第二个moveToPoint更改为lineToPoint

修复后,我发现这段代码非常有用。 注意:您可能还需要dealloc 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

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]

}

3
为什么这会让事情变得更快? - Lawrence Kesteloot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接