#cocoa #drawing #line #nsview
#cocoa #рисование #строка #nsview
Вопрос:
Я не смог найти ни одного примитива рисования линий в Cocoa на уровне NSView. Единственное, что я нашел, это NSBezierPath
. Является ли это предпочтительным способом? Или есть другой способ, который я не смог обнаружить?
Ответ №1:
NSBezierPath
это именно то, что вы должны использовать. Если вы просто хотите провести прямую линию из одной точки в другую, используйте метод class:
strokeLineFromPoint:(NSPoint)point1 toPoint:(NSPoint)point2
Ответ №2:
Cocoa использует неявный стек рисования и модель недействительности. В вашем NSView при изменении состояния, которое может привести к тому, что вид будет отображаться по-другому, вы вызываете -[self setNeedsDisplay:], чтобы сообщить системе рисования, что вам нужно перерисовать. В какой-то момент в самом ближайшем будущем, фактически в конце текущего цикла событий, будет вызван drawRect: метод вашего представления. Это ваша возможность нарисовать все, что вы захотите.
Существует неявный стек фокусировки, означающий, что при вызове drawRect: вашего представления рисунок фокусируется и обрезается до границ вашего представления в окне, в котором он находится. Затем вы можете вызывать такие функции, как [[NSColor redColor] set]; и NSRectFill([собственные границы]);
Вот пример:
@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
В представлении должна быть нарисована диагональная линия, и при каждом нажатии на нее линия должна менять цвет.
Комментарии:
1. Второй вызов moveToPoint в методе darRect должен быть вызовом lineToPoint.
Ответ №3:
Я попробовал пример, приведенный Джоном, и обнаружил, что мне нужно добавить 2 незначительных исправления в приведенный выше пример кода.
- вставьте распределитель NSColor в блок инициализации
- измените вторую точку перемещения так, чтобы она стала точкой линии
Как только я это исправил, я нашел фрагмент кода очень полезным. ПРИМЕЧАНИЕ: вероятно, вам также нужно освободить значение 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
Ответ №4:
Просто чтобы добавить некоторую информацию, у меня вошло в привычку следить за тем, чтобы состояние графики сохранялось и восстанавливалось до и после рисования, чтобы все было живо.
- (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]
}
Комментарии:
1. Почему это делает процесс быстрым?