Reputation: 2074
I have a custom NSView with some drawing:
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
}
}
It works, but lines appear only after hiding and bringing the window back. I'm looking for the code to write in updateTheView
function to make the view update every time the mouseDragged is activated
Upvotes: 0
Views: 4699
Reputation: 36295
You need to put the NSBezier stroke
in the drawRect
, not in the mouseDragged
. Save the coordinates in mouseDragged
in an instance array and then do the final drawing with Bezier in drawRect
.
drawRect
is called by the OS when the view needs display (either being told by needsDisplay = true
from somewhere or when the window is moved). In the mouse-move routine just store the path. Then when it comes to drawing drawRect
will actually draw the line.
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
}
}
I tested it with a plain view in a window.
Upvotes: 2
Reputation: 3429
You're most likely not calling a method like setNeedsDisplay on the views to force a re drawing on the screen (this would be called when you hide/show the view again forcing the view to re draw itself). Here's a useful link if you don't know a view's life cycle that will help you with custom drawing:
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
Upvotes: 1
Reputation: 22343
You can use the display()
method to force the view to reload.
Just call that function on your main-view.
Documentation
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.
Upvotes: 0