Objective-C | NSBezierPath 在动作上绘制和着色
Objective-C | NSBezierPath draw and color on action
我有一个带有跟踪区域的自定义视图 class。我想要的是,当鼠标进入跟踪区域时,用一种颜色绘制贝塞尔曲线,当鼠标离开该区域时,贝塞尔曲线消失。为了让它消失,我读到唯一的方法是用 window 背景颜色改变它的颜色。
我成功添加了跟踪区域,但我不知道如何绘制贝塞尔曲线。如果我把代码放在
-(void)drawRect:(NSRect)dirtyRect
它是在应用程序启动时绘制的,但我不想这样。我试过这个:
@implementation MSBezier
- (void) viewWillMoveToWindow:(NSWindow *)newWindow {
// Setup a new tracking area when the view is added to the window.
NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:NSMakeRect(164.5, 17.5, 270, 65) options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
}
- (void) mouseEntered:(NSEvent*)theEvent {
NSLog(@"Entered");
color = [NSColor colorWithCalibratedRed: 0.044 green: 0.813 blue: 0.044 alpha: 0.441];
CGFloat rectangleCornerRadius = 31;
NSRect rectangleRect = NSMakeRect(164.5, 17.5, 270, 65);
NSRect rectangleInnerRect = NSInsetRect(rectangleRect, rectangleCornerRadius, rectangleCornerRadius);
rectanglePath = NSBezierPath.bezierPath;
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMinX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 180 endAngle: 270];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 270 endAngle: 360];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMaxY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 0 endAngle: 90];
[rectanglePath lineToPoint: NSMakePoint(NSMinX(rectangleRect), NSMaxY(rectangleRect))];
[rectanglePath closePath];
[color setStroke];
[rectanglePath setLineWidth: 3];
[rectanglePath stroke];
}
- (void) mouseExited:(NSEvent*)theEvent {
NSLog(@"Exited");
color = [NSColor colorWithCalibratedRed: 0.949 green: 0.949 blue: 0.949 alpha: 1];
CGFloat rectangleCornerRadius = 31;
NSRect rectangleRect = NSMakeRect(164.5, 17.5, 270, 65);
NSRect rectangleInnerRect = NSInsetRect(rectangleRect, rectangleCornerRadius, rectangleCornerRadius);
rectanglePath = NSBezierPath.bezierPath;
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMinX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 180 endAngle: 270];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 270 endAngle: 360];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMaxY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 0 endAngle: 90];
[rectanglePath lineToPoint: NSMakePoint(NSMinX(rectangleRect), NSMaxY(rectangleRect))];
[rectanglePath closePath];
[color setStroke];
[rectanglePath setLineWidth: 3];
[rectanglePath stroke];
}
@end
但是没有绘制贝塞尔曲线。
感谢您的帮助!
编辑
@uchugaka
这是目前为止的代码,似乎什么都没做:
@implementation MSBezier
bool shouldDrawMyPath = YES;
NSBezierPath *rectanglePath;
- (void)viewWillDraw {
if (shouldDrawMyPath == YES) {
NSColor *color = [NSColor colorWithCalibratedRed: 0.044 green: 0.813 blue: 0.044 alpha: 0.441];
CGFloat rectangleCornerRadius = 31;
NSRect rectangleRect = NSMakeRect(164.5, 17.5, 270, 65);
NSRect rectangleInnerRect = NSInsetRect(rectangleRect, rectangleCornerRadius, rectangleCornerRadius);
rectanglePath = NSBezierPath.bezierPath;
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMinX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 180 endAngle: 270];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 270 endAngle: 360];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMaxY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 0 endAngle: 90];
[rectanglePath lineToPoint: NSMakePoint(NSMinX(rectangleRect), NSMaxY(rectangleRect))];
[rectanglePath closePath];
[color setStroke];
[rectanglePath setLineWidth: 3];
} else {
rectanglePath = nil;
}
}
- (void)drawRect:(NSRect)dirtyRect {
[[NSColor clearColor] set];
NSRectFill(self.bounds);
if (shouldDrawMyPath == YES) {
[rectanglePath stroke];
}
}
- (void) viewWillMoveToWindow:(NSWindow *)newWindow {
NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:NSMakeRect(164.5, 17.5, 270, 65) options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
}
- (void) mouseEntered:(NSEvent*)theEvent {
NSLog(@"Entered");
shouldDrawMyPath = YES;
[self setNeedsDisplay:YES];
}
- (void) mouseExited:(NSEvent*)theEvent {
NSLog(@"Exited");
shouldDrawMyPath = NO;
[self setNeedsDisplay:YES];
}
@end
我确定我做错了什么。
编辑 2
我只需要在 drawRect:
中设置颜色。所以:
-(void)drawRect:(NSRect)dirtyRect {
if (shouldDrawMyPath == YES) {
NSColor *color = [NSColor colorWithCalibratedRed: 0.044 green: 0.813 blue: 0.044 alpha: 0.441];
[color setStroke];
[rectanglePath stroke];
}
}
所以这很简单。
你需要重新安排事情。
首先创建一个 BOOL 属性 像 shouldDrawMyPath
这应该默认为 NO。
接下来,在mouseEntered中:
将其设置为是
调用自己setNeedsDisplay:YES
接下来,mouseExited:
将其设置为否
调用自己setNeedsDisplay:YES
添加一个 NSBezierPath 属性。
在viewWillDraw中
如果 shouldDrawMyPath == YES
设置您的贝塞尔曲线路径。
否则将其设置为零
(我假设您的视图可能会随时调整大小)
如果您的视图永远不会调整大小,您可以创建一次路径。
在drawRect中
首先清除面板,特别是如果您的视图可以调整大小。
[[NSColor clearColor] 设置];
NSRectFill(self.bounds);
如果有的话,总是在那里画任何东西。
如果 shouldDrawMyPath == YES
填充 and/or 描边你的路径。
别的
在没有路径的情况下做任何其他绘图。
只要您正确设置了跟踪区域,就可以顺利进行。
根据具体情况,总会有优化。
除非您知道自己在做什么,否则切勿在 drawRect 之外绘制。
保持 drawRect 代码简单。
只在需要的时候画你需要的东西。 (你还没有做到这一点,但是可以做很多优化来使特定的矩形无效并只绘制特定的矩形)
我有一个带有跟踪区域的自定义视图 class。我想要的是,当鼠标进入跟踪区域时,用一种颜色绘制贝塞尔曲线,当鼠标离开该区域时,贝塞尔曲线消失。为了让它消失,我读到唯一的方法是用 window 背景颜色改变它的颜色。
我成功添加了跟踪区域,但我不知道如何绘制贝塞尔曲线。如果我把代码放在
-(void)drawRect:(NSRect)dirtyRect
它是在应用程序启动时绘制的,但我不想这样。我试过这个:
@implementation MSBezier
- (void) viewWillMoveToWindow:(NSWindow *)newWindow {
// Setup a new tracking area when the view is added to the window.
NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:NSMakeRect(164.5, 17.5, 270, 65) options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
}
- (void) mouseEntered:(NSEvent*)theEvent {
NSLog(@"Entered");
color = [NSColor colorWithCalibratedRed: 0.044 green: 0.813 blue: 0.044 alpha: 0.441];
CGFloat rectangleCornerRadius = 31;
NSRect rectangleRect = NSMakeRect(164.5, 17.5, 270, 65);
NSRect rectangleInnerRect = NSInsetRect(rectangleRect, rectangleCornerRadius, rectangleCornerRadius);
rectanglePath = NSBezierPath.bezierPath;
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMinX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 180 endAngle: 270];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 270 endAngle: 360];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMaxY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 0 endAngle: 90];
[rectanglePath lineToPoint: NSMakePoint(NSMinX(rectangleRect), NSMaxY(rectangleRect))];
[rectanglePath closePath];
[color setStroke];
[rectanglePath setLineWidth: 3];
[rectanglePath stroke];
}
- (void) mouseExited:(NSEvent*)theEvent {
NSLog(@"Exited");
color = [NSColor colorWithCalibratedRed: 0.949 green: 0.949 blue: 0.949 alpha: 1];
CGFloat rectangleCornerRadius = 31;
NSRect rectangleRect = NSMakeRect(164.5, 17.5, 270, 65);
NSRect rectangleInnerRect = NSInsetRect(rectangleRect, rectangleCornerRadius, rectangleCornerRadius);
rectanglePath = NSBezierPath.bezierPath;
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMinX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 180 endAngle: 270];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 270 endAngle: 360];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMaxY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 0 endAngle: 90];
[rectanglePath lineToPoint: NSMakePoint(NSMinX(rectangleRect), NSMaxY(rectangleRect))];
[rectanglePath closePath];
[color setStroke];
[rectanglePath setLineWidth: 3];
[rectanglePath stroke];
}
@end
但是没有绘制贝塞尔曲线。
感谢您的帮助!
编辑 @uchugaka
这是目前为止的代码,似乎什么都没做:
@implementation MSBezier
bool shouldDrawMyPath = YES;
NSBezierPath *rectanglePath;
- (void)viewWillDraw {
if (shouldDrawMyPath == YES) {
NSColor *color = [NSColor colorWithCalibratedRed: 0.044 green: 0.813 blue: 0.044 alpha: 0.441];
CGFloat rectangleCornerRadius = 31;
NSRect rectangleRect = NSMakeRect(164.5, 17.5, 270, 65);
NSRect rectangleInnerRect = NSInsetRect(rectangleRect, rectangleCornerRadius, rectangleCornerRadius);
rectanglePath = NSBezierPath.bezierPath;
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMinX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 180 endAngle: 270];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMinY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 270 endAngle: 360];
[rectanglePath appendBezierPathWithArcWithCenter: NSMakePoint(NSMaxX(rectangleInnerRect), NSMaxY(rectangleInnerRect)) radius: rectangleCornerRadius startAngle: 0 endAngle: 90];
[rectanglePath lineToPoint: NSMakePoint(NSMinX(rectangleRect), NSMaxY(rectangleRect))];
[rectanglePath closePath];
[color setStroke];
[rectanglePath setLineWidth: 3];
} else {
rectanglePath = nil;
}
}
- (void)drawRect:(NSRect)dirtyRect {
[[NSColor clearColor] set];
NSRectFill(self.bounds);
if (shouldDrawMyPath == YES) {
[rectanglePath stroke];
}
}
- (void) viewWillMoveToWindow:(NSWindow *)newWindow {
NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:NSMakeRect(164.5, 17.5, 270, 65) options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
}
- (void) mouseEntered:(NSEvent*)theEvent {
NSLog(@"Entered");
shouldDrawMyPath = YES;
[self setNeedsDisplay:YES];
}
- (void) mouseExited:(NSEvent*)theEvent {
NSLog(@"Exited");
shouldDrawMyPath = NO;
[self setNeedsDisplay:YES];
}
@end
我确定我做错了什么。
编辑 2
我只需要在 drawRect:
中设置颜色。所以:
-(void)drawRect:(NSRect)dirtyRect {
if (shouldDrawMyPath == YES) {
NSColor *color = [NSColor colorWithCalibratedRed: 0.044 green: 0.813 blue: 0.044 alpha: 0.441];
[color setStroke];
[rectanglePath stroke];
}
}
所以这很简单。 你需要重新安排事情。 首先创建一个 BOOL 属性 像 shouldDrawMyPath 这应该默认为 NO。
接下来,在mouseEntered中: 将其设置为是 调用自己setNeedsDisplay:YES
接下来,mouseExited: 将其设置为否 调用自己setNeedsDisplay:YES
添加一个 NSBezierPath 属性。 在viewWillDraw中 如果 shouldDrawMyPath == YES 设置您的贝塞尔曲线路径。 否则将其设置为零 (我假设您的视图可能会随时调整大小) 如果您的视图永远不会调整大小,您可以创建一次路径。
在drawRect中 首先清除面板,特别是如果您的视图可以调整大小。 [[NSColor clearColor] 设置]; NSRectFill(self.bounds);
如果有的话,总是在那里画任何东西。
如果 shouldDrawMyPath == YES 填充 and/or 描边你的路径。 别的 在没有路径的情况下做任何其他绘图。
只要您正确设置了跟踪区域,就可以顺利进行。
根据具体情况,总会有优化。
除非您知道自己在做什么,否则切勿在 drawRect 之外绘制。
保持 drawRect 代码简单。
只在需要的时候画你需要的东西。 (你还没有做到这一点,但是可以做很多优化来使特定的矩形无效并只绘制特定的矩形)