使用函数 swift 自动更新 NSView

update NSView automatically with the function swift

我有一个带有一些绘图的自定义 NSView:

class ViewController: NSViewController {

@IBOutlet weak var mainView: LineDrawer!
var time = NSTimer()
override func viewDidLoad() {
    super.viewDidLoad()
    self.view.needsDisplay = true
    // Do any additional setup after loading the view.
}

override var representedObject: AnyObject? {
    didSet {
        // Update the view, if already loaded.
    }
}


}


class LineDrawer : NSView {
required init?(coder  aDecoder : NSCoder) {
    super.init(coder: aDecoder)
}

var lastPt : CGPoint!
var newPt : CGPoint!
var tmp = CGPoint()
override func viewWillDraw() {
    super.viewWillDraw()
    lastPt = newPt
}

override func drawRect(dirtyRect: NSRect) {
    super.drawRect(dirtyRect)
    self.needsDisplay = true
    NSColor.redColor().set()
    var newLinear = NSBezierPath()
    newLinear.moveToPoint(NSMakePoint(newPt.x, newPt.y))
    newLinear.lineToPoint(NSMakePoint(tmp.x, tmp.y))
    newLinear.lineWidth = 1
    newLinear.stroke()
    println(1)
}

override func mouseDown(theEvent: NSEvent) {
    super.mouseDown(theEvent)
    let location = theEvent.locationInWindow
    lastPt = theEvent.locationInWindow
    tmp = lastPt
}

override func mouseDragged(theEvent: NSEvent) {
    super.mouseDragged(theEvent)
    newPt = theEvent.locationInWindow
    self.drawRect(self.frame)
    tmp = newPt

}

}

它可以工作,但只有在隐藏并将 window 带回来后才会出现线条。我正在寻找要在 updateTheView 函数中编写的代码,以便在每次激活 mouseDragged 时更新视图

您可以使用display() 方法强制重新加载视图。

只需在主视图上调用该函数即可。

文档

If the receiver isn’t opaque, this method backs up the view hierarchy to the first opaque ancestor, calculates the portion of the opaque ancestor covered by the receiver, and begins displaying from there.

您很可能不会在视图上调用 setNeedsDisplay 之类的方法来强制在屏幕上重新绘制(当您 hide/show 视图再次强制视图重新绘制时会调用此方法) .如果您不知道视图的生命周期,这里有一个有用的 link 可以帮助您进行自定义绘图:

raywenderlich custom controls

setNeedsDisplay()

Discussion Whenever the data or state used for drawing a view object changes, the view should be sent a setNeedsDisplay: message. NSView objects marked as needing display are automatically redisplayed on each pass through the application’s event loop. (View objects that need to redisplay before the event loop comes around can of course immediately be sent the appropriate display... method.)

Sample drawing iOS application

您需要将 NSBezier stroke 放在 drawRect 中,而不是 mouseDragged 中。将 mouseDragged 中的坐标保存在实例数组中,然后在 drawRect.

中使用贝塞尔曲线进行最终绘制

drawRect 在视图需要显示时由 OS 调用(由 needsDisplay = true 从某处告知或当 window 移动时调用)。在鼠标移动例程中,只需存储路径。然后画的时候drawRect其实会画线

class LineDrawer : NSView {
  var newLinear = NSBezierPath()

  override func drawRect(dirtyRect: NSRect) {
    NSColor.redColor().set()
    newLinear.lineWidth = 1
    newLinear.stroke()
  }

  override func mouseDown(theEvent: NSEvent) {
    super.mouseDown(theEvent)
    let location = theEvent.locationInWindow
    var lastPt = theEvent.locationInWindow
    lastPt.x -= frame.origin.x
    lastPt.y -= frame.origin.y
    newLinear.moveToPoint(lastPt)
  }

  override func mouseDragged(theEvent: NSEvent) {
    super.mouseDragged(theEvent)
    var newPt = theEvent.locationInWindow
    newPt.x -= frame.origin.x
    newPt.y -= frame.origin.y
    newLinear.lineToPoint(newPt)
    needsDisplay = true
  }
}

我在 window.

中用普通视图测试了它