2016-07-06 139 views
0

我试图做一个简单的绘图应用程序(OSX的Mac应用程序),我想弄清楚用户如何通过两次鼠标点击画一条线,例如,第一次点击鼠标(mouseDown然后mouseUP)会标记该行的原点,然后第二次鼠标单击(mouseDown然后mouseUP)将标记该行的结束点。在用户第二次点击结束点之前,我希望将线条(在锚定结束点之前)直播,就像在Photoshop中一样。 Objective-C和Swift都很好。如何使用两次鼠标点击绘制直线代码(OSX Mac App)?

到目前为止,我已经有了...

var newLinear = NSBezierPath() 

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

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

干杯!

+0

使用二进制状态机'var gotFirstPoint = false',在mouseClick上设置为'true'(如果false),并保存原点,在mouseMove中检查值,如果为true,则重绘,如果为true, ? – Grimxn

+0

到目前为止,我可以通过拖动来绘制线条,但即使拖动它,我也看不到线条。我想要拖动的线路直播。 – sundrius

+0

在mouseMove例程中,您需要捕捉终点并设置视图的'needsDisplay',然后在'drawRect'中检查您是否正在拖动并画线。应该工作得很好...... – Grimxn

回答

0

enum与关联的值是非常适合您的应用程序扩展并可能添加其他工具和状态。

enum State { 
    case normal 
    case drawingLine(from: CGPoint, to: CGPoint) 
} 
var state = State.normal 

override func mouseDown(theEvent: NSEvent) { 
    super.mouseDown(theEvent) 
    var lastPoint = theEvent.locationInWindow 
    lastPoint.x -= frame.origin.x 
    lastPoint.y -= frame.origin.y 
    state = .drawingLine(from: lastPoint, to: lastPoint) 
} 

override func mouseUp(theEvent: NSEvent) { 
    if case .drawingLine(let firstPoint, _) = state { 
     var newPoint = theEvent.locationInWindow 
     newPoint.x -= frame.origin.x 
     newPoint.y -= frame.origin.y 
     //finalize line from `firstPoint` to `newPoint` 
    } 
} 

override func mouseMoved(theEvent: NSEvent) { 
    if case .drawingLine(let firstPoint, _) = state { 
     needsDisplay = true 
     var newPoint = theEvent.locationInWindow 
     newPoint.x -= frame.origin.x 
     newPoint.y -= frame.origin.y 
     state = .drawingLine(from: firstPoint, to: newPoint) 
    } 
} 

override func draw(_ dirtyRect: NSRect) { 
    if case .drawingLine(let firstPoint, let secondPoint) = state { 
     //draw your line from `firstPoint` to `secondPoint` 
    } 
} 
+0

感谢您的回复andyvn22。我试过你的代码,但是我无法让它工作。代码看起来非常棒,但我仍然是初学者,所以我想知道你是否可以进一步帮助我呢?干杯! – sundrius

+0

没问题 - 如果你能确定什么给你带来麻烦,你可以问一个关于它的新问题(它是如何在重写的'draw(_ :)'中画一条线?)或者可能找到一个已经回答的问题。 – andyvn22

0

我明白你在这里试图实现的目标!所以,我已经在andyvn22的解决方案中增加了一些代码,以帮助您的努力,请注意:为了简单起见,开始一个新的“Xcode项目”,我们可以确保一切都被覆盖在一起。

在您的新项目中,右键单击'ViewController.swift'并添加新文件...选择'Cocoa Class'并单击下一步,将该文件命名为'DrawingView'确保Subclass:'NSView'并选择Next。

现在您完成了,可以设置您的界面,输入'Main.storyboard'并拖放'自定义视图',确保根据您的偏好添加约束。现在在选择“自定义视图”的情况下输入您的“身份检查器”,并在顶部添加“DrawingView”到Class。

我希望这是有道理的!确定打开'Assistant Editor',这样你就可以同时查看'ViewController.swift'和'Main.storyboard',右键单击并从'Custom View'拖动到'ViewController.swift',命名为'draw'并选择connect。

您会注意到Xcode已经自动将@IBOutlet更新到您的子类中,并且您的'ViewController.swift'如下所示。

进口可可

类的ViewController:NSViewController {

@IBOutlet var draw: DrawingView! 

override func viewDidLoad() { 
    super.viewDidLoad() 

    // Do any additional setup after loading the view. 
} 

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

}

现在选择 'DrawingView.swift' 文件并清除网页上的所有内容,突出下面的代码,复制粘贴到你的项目中。

进口可可

类DrawingView:{的NSView

// >>>CODE ADDED BY LC<<< 
private var path: NSBezierPath = { 
    let path = NSBezierPath() 
    path.lineWidth = 50.0 
    path.lineJoinStyle = .roundLineJoinStyle 
    path.lineCapStyle = .roundLineCapStyle 
    return path 
}() 

enum State { 
    case normal 
    case drawingLine(from: CGPoint, to: CGPoint) 
} 
var state = State.normal 

override func mouseDown(with event: NSEvent) { 
    super.mouseDown(with: event) 
    var lastPoint = event.locationInWindow 
    lastPoint.x -= frame.origin.x 
    lastPoint.y -= frame.origin.y 
    state = .drawingLine(from: lastPoint, to: lastPoint) 
} 

override func mouseUp(with event: NSEvent) { 
    if case .drawingLine(let firstPoint, _) = state { 
     var newPoint = event.locationInWindow 
     newPoint.x -= frame.origin.x 
     newPoint.y -= frame.origin.y 

     // >>>CODE ADDED BY LC<<< 
     path.move(to: convert(event.locationInWindow, from: nil)) 
     path.line(to: firstPoint) 
     needsDisplay = true 
    } 
} 

override func draw(_ dirtyRect: NSRect) { 
    if case .drawingLine(let firstPoint, let secondPoint) = state { 

     // >>>CODE ADDED BY LC<<< 
     NSColor.orange.set() 
     path.lineWidth = 5.0 
     path.stroke() 
     path.line(to: firstPoint) 
     path.line(to: secondPoint) 
    } 
} 

}

一切都应该按预期投放,您将不能画一个喝醉酒的生产线。我希望这有助于并随时回复更多信息。