【发布时间】:2016-04-13 22:47:23
【问题描述】:
我在 NSView 级别的 Cocoa 中找不到任何线条绘制原语。我唯一找到的是NSBezierPath。这是首选方式吗?还是有其他我没发现的方法?
【问题讨论】:
我在 NSView 级别的 Cocoa 中找不到任何线条绘制原语。我唯一找到的是NSBezierPath。这是首选方式吗?还是有其他我没发现的方法?
【问题讨论】:
NSBezierPath 正是您应该使用的。如果你只是想从一个点到另一个点画一条直线,使用类方法:
+strokeLineFromPoint:(NSPoint)point1 toPoint:(NSPoint)point2
【讨论】:
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
视图应该画一条对角线,并且每次点击它都会改变颜色。
【讨论】:
我尝试了 Jon 给出的示例,发现我需要在上面的代码示例中添加 2 个小修复。
一旦我解决了这个问题,我发现代码片段非常有用。 注意:您可能还需要释放 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
【讨论】:
只是为了补充一些信息,我养成了确保图形状态在绘制前后保存和恢复的习惯,以保持流畅。
- (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]
}
【讨论】: