【问题标题】:What's the preferred/recommended way to draw a line in NSView-drawRect: method?在 NSView-drawRect: 方法中画线的首选/推荐方法是什么?
【发布时间】:2016-04-13 22:47:23
【问题描述】:

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

【问题讨论】:

    标签: cocoa drawing line nsview


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      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 调用。
      【解决方案3】:

      我尝试了 Jon 给出的示例,发现我需要在上面的代码示例中添加 2 个小修复。

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

      一旦我解决了这个问题,我发现代码片段非常有用。 注意:您可能还需要释放 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]
        
        }
        

        【讨论】:

        • 为什么这会让事情变得活泼?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-19
        • 2019-09-15
        • 1970-01-01
        • 1970-01-01
        • 2021-11-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多