Какой предпочтительный / рекомендуемый способ рисования линии в NSView-drawRect: метод?

#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 незначительных исправления в приведенный выше пример кода.

  1. вставьте распределитель NSColor в блок инициализации
  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
  

Ответ №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. Почему это делает процесс быстрым?