2016-07-06 22 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) 
    } 
} 

}

一切都應該按預期投放,您將不能畫一個喝醉酒的生產線。我希望這有助於並隨時回覆更多信息。