我正在尝试制作一个简单的绘图应用程序(OSX Mac 应用程序),我正在尝试弄清楚用户如何通过两次鼠标单击来绘制线条,例如,第一次鼠标单击(鼠标按下然后鼠标向上)将标记线的原点,第二次鼠标单击(鼠标向下然后鼠标向上)将标记线的终点。在用户第二次单击终点之前,我希望该行(在锚定终点之前)实时显示,有点像在 photoshop 中一样。Objective-C 和 Swift 都很好。
到目前为止,我已经...
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
}
干杯!
具有关联值的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`
}
}
我明白你在这里想要实现的目标!因此,我在 andyvn22 的解决方案中添加了几行代码,可以帮助您完成工作,请注意:为了简单起见,开始一个新的"Xcode 项目",我们可以确保所有内容都涵盖在一起。
在您的新项目中,右键单击"视图控制器.swift"并添加新文件...选择"Cocoa 类"并单击"下一步",将此文件命名为"绘图视图",确保子类为:"NSView",然后选择"下一步"。
现在您完成了设置界面,输入"Main.storyboard"并拖放"自定义视图",确保根据您的喜好添加约束。现在,在选择"自定义视图"时输入"身份检查器",并将"绘图视图"添加到顶部的"类"。
我希望到目前为止这是有意义的!好的,打开"助理编辑器",以便您可以同时查看"视图控制器.swift"和"主故事板",右键单击并从"自定义视图"拖动到"视图控制器.swift",将其命名为"绘制"并选择连接。
你会注意到 Xcode 已经自动更新了@IBOutlet到你的子类,你的"ViewController.swift"看起来像下面的例子。
import Cocoa
class 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"文件并清除页面上的所有内容,突出显示下面的代码,复制并粘贴到您的项目中。
import Cocoa
class 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)
}
}
}
一切都应该按预期运行,您将无法画出一条混乱的线。我希望这有所帮助,并随时回复更多信息。