在 Mac OS X 中使用 swift 我想在 运行 时移动标签/文本框控件?
In Mac OS X using swift I want to move label / textbox controls at run-time?
已更新 -- 我现在可以使用以下代码拖动任何 NSTextField 控件:
ViewController.swift
class ViewController: NSViewController {
@IBAction override func mouseDragged(theEvent: NSEvent) {
let dragPoint = theEvent.locationInWindow
//var newDragLocation = NSPoint()
print( "dragPoint X,Y = \(dragPoint)" )
if controlToMove != nil {
//newDragLocation = (controlToMove!.convertPoint(dragPoint, fromView: nil))
//print( "newDragLocation X,Y = \(newDragLocation)" )
var cntrl_location = NSRect();
cntrl_location = controlToMove!.frame
print( "cntrl_location X,Y = \(cntrl_location)" )
let previousLocation = cntrl_location
//I think this is the problem with the current dragging? - my location is not the dragPoint
//it is the dragPoint minus/plus some offset to the control frame origin???
var location = CGPoint()
location = dragPoint
var delta_x = CGFloat()
var delta_y = CGFloat()
delta_x = location.x - previousLocation.origin.x
delta_y = location.y - previousLocation.origin.y
print( "delta X,Y = \(delta_x), \(delta_y)" )
// move label
cntrl_location.origin = CGPointMake(location.x + delta_x, location.y + delta_y);
print( "cntrl_location.orgin = \(cntrl_location.origin)" )
// save the new drag location for the next drag event
//lastDragLocation=newDragLocation
controlToMove!.frame = cntrl_location
print( "controlToMove.frame X,Y = \(controlToMove?.frame)" )
lastLocation = cntrl_location.origin
}
}
但它有一个非常小的问题:当我拖动标签或文本字段控件时,其中两个会在我拖动时前后闪烁。它与一个出现在鼠标位置和一个出现在新的控制框或原点位置有关,当我拖动时交替来回和第四。我只是还不能弄清楚拖动的正确逻辑?
好的,我终于找到了一个解决方案,解决了如何在 Mac OS X 中围绕视图拖动 Label 或 TextField (NSTextField) 控件的问题。我已经确定了解决方案:
在ViewControllerclass中创建一个属性
class ViewController: NSViewController {
var mouseDownLocation: CGPoint?
}
在覆盖mouseDown事件中
var mouseDownEvent: NSEvent?
@IBAction override func mouseDown(theEvent: NSEvent) {
var event_location: NSPoint!
event_location = theEvent.locationInWindow
var cntrl_id = NSTextField()
var cntrl_frame = NSRect()
var cntrl_name = String()
var cntrl_value = String()
var hit = Bool()
for view in self.view.subviews as [NSView] {
if let ct = view as? NSTextField {
cntrl_name = ct.identifier!
cntrl_id = ct
cntrl_frame = ct.frame
cntrl_value = ct.stringValue
hit = cntrl_frame.contains(event_location)
if hit {
controlToMove = cntrl_id
lastLocation = controlToMove?.frame.origin
break
}
}
}
//figure out the difference of where the mouse went down at in the
//control frame in relation to the control frame origin
let dx = event_location.x - (controlToMove?.frame.origin.x)!
let dy = event_location.y - (controlToMove?.frame.origin.y)!
let mouseDownInCntrlFrame = CGPoint(x: dx, y: dy)
mouseDownLocation = mouseDownInCntrlFrame
}
现在在覆盖 mouseDragged 事件中
@IBAction override func mouseDragged(theEvent: NSEvent) {
let dragPoint = theEvent.locationInWindow
if controlToMove != nil {
var cntrl_location = CGPoint();
cntrl_location.x = controlToMove!.frame.origin.x
cntrl_location.y = controlToMove!.frame.origin.y
print( "cntrl_location X,Y = \(cntrl_location)" )
let previousLocation = cntrl_location
var location = CGPoint()
location = dragPoint
location.x -= (mouseDownLocation?.x)!
location.y -= (mouseDownLocation?.y)!
var delta_x = CGFloat()
var delta_y = CGFloat()
delta_x = location.x - previousLocation.x
delta_y = location.y - previousLocation.y
// move label
cntrl_location = CGPointMake(location.x + delta_x, location.y + delta_y);
controlToMove!.frame.origin.x = cntrl_location.x
controlToMove!.frame.origin.y = cntrl_location.y
}
}
这将允许您在单击并拖动的视图周围拖动任何 NSTextField。它不像我希望的那样流畅,当您在视图中拖动控件时,它只是有点希望。但是考虑到互联网上没有任何关于如何拖动 OS X 控件的其他信息(有几个博客和信息关于如何拖动图像 - 但即使是那些更像是拖放在视图周围的 swift 中键入解决方案)这是一个有效的解决方案。我相信有经验的 OS X Xcode 大师可以改进这个解决方案 - 如果有经验的 OS X 开发人员希望做出贡献,我欢迎对此解决方案进行改进。
感谢您的代码!它帮助了我。
我遇到了你说的同样的问题,移动的元素反弹。
我怀疑这是因为 mouseDragged 被调用了几次,并且你得到了一个原始位置,当计算新位置时,它可能已经发生了变化。
我重建移动方法,使用单行(以避免 mouseDragged 调用之间的冲突)并在调用 mouseDown 时使用元素位置。
当然这不是最好的方法,它只是消除弹跳问题的替代方法。
override func mouseDragged(with event: NSEvent) {
let dragPoint = event.locationInWindow
if controlToMove != nil {
controlToMove!.setFrameOrigin(NSPoint(x: (lastLocation?.x)! + (dragPoint.x - (mouseDownLocation?.x)!), y: (lastLocation?.y)! + (dragPoint.y - (mouseDownLocation?.y)!)));
}
}
希望对您有所帮助!
已更新 -- 我现在可以使用以下代码拖动任何 NSTextField 控件:
ViewController.swift
class ViewController: NSViewController {
@IBAction override func mouseDragged(theEvent: NSEvent) {
let dragPoint = theEvent.locationInWindow
//var newDragLocation = NSPoint()
print( "dragPoint X,Y = \(dragPoint)" )
if controlToMove != nil {
//newDragLocation = (controlToMove!.convertPoint(dragPoint, fromView: nil))
//print( "newDragLocation X,Y = \(newDragLocation)" )
var cntrl_location = NSRect();
cntrl_location = controlToMove!.frame
print( "cntrl_location X,Y = \(cntrl_location)" )
let previousLocation = cntrl_location
//I think this is the problem with the current dragging? - my location is not the dragPoint
//it is the dragPoint minus/plus some offset to the control frame origin???
var location = CGPoint()
location = dragPoint
var delta_x = CGFloat()
var delta_y = CGFloat()
delta_x = location.x - previousLocation.origin.x
delta_y = location.y - previousLocation.origin.y
print( "delta X,Y = \(delta_x), \(delta_y)" )
// move label
cntrl_location.origin = CGPointMake(location.x + delta_x, location.y + delta_y);
print( "cntrl_location.orgin = \(cntrl_location.origin)" )
// save the new drag location for the next drag event
//lastDragLocation=newDragLocation
controlToMove!.frame = cntrl_location
print( "controlToMove.frame X,Y = \(controlToMove?.frame)" )
lastLocation = cntrl_location.origin
}
}
但它有一个非常小的问题:当我拖动标签或文本字段控件时,其中两个会在我拖动时前后闪烁。它与一个出现在鼠标位置和一个出现在新的控制框或原点位置有关,当我拖动时交替来回和第四。我只是还不能弄清楚拖动的正确逻辑?
好的,我终于找到了一个解决方案,解决了如何在 Mac OS X 中围绕视图拖动 Label 或 TextField (NSTextField) 控件的问题。我已经确定了解决方案:
在ViewControllerclass中创建一个属性
class ViewController: NSViewController {
var mouseDownLocation: CGPoint?
}
在覆盖mouseDown事件中
var mouseDownEvent: NSEvent?
@IBAction override func mouseDown(theEvent: NSEvent) {
var event_location: NSPoint!
event_location = theEvent.locationInWindow
var cntrl_id = NSTextField()
var cntrl_frame = NSRect()
var cntrl_name = String()
var cntrl_value = String()
var hit = Bool()
for view in self.view.subviews as [NSView] {
if let ct = view as? NSTextField {
cntrl_name = ct.identifier!
cntrl_id = ct
cntrl_frame = ct.frame
cntrl_value = ct.stringValue
hit = cntrl_frame.contains(event_location)
if hit {
controlToMove = cntrl_id
lastLocation = controlToMove?.frame.origin
break
}
}
}
//figure out the difference of where the mouse went down at in the
//control frame in relation to the control frame origin
let dx = event_location.x - (controlToMove?.frame.origin.x)!
let dy = event_location.y - (controlToMove?.frame.origin.y)!
let mouseDownInCntrlFrame = CGPoint(x: dx, y: dy)
mouseDownLocation = mouseDownInCntrlFrame
}
现在在覆盖 mouseDragged 事件中
@IBAction override func mouseDragged(theEvent: NSEvent) {
let dragPoint = theEvent.locationInWindow
if controlToMove != nil {
var cntrl_location = CGPoint();
cntrl_location.x = controlToMove!.frame.origin.x
cntrl_location.y = controlToMove!.frame.origin.y
print( "cntrl_location X,Y = \(cntrl_location)" )
let previousLocation = cntrl_location
var location = CGPoint()
location = dragPoint
location.x -= (mouseDownLocation?.x)!
location.y -= (mouseDownLocation?.y)!
var delta_x = CGFloat()
var delta_y = CGFloat()
delta_x = location.x - previousLocation.x
delta_y = location.y - previousLocation.y
// move label
cntrl_location = CGPointMake(location.x + delta_x, location.y + delta_y);
controlToMove!.frame.origin.x = cntrl_location.x
controlToMove!.frame.origin.y = cntrl_location.y
}
}
这将允许您在单击并拖动的视图周围拖动任何 NSTextField。它不像我希望的那样流畅,当您在视图中拖动控件时,它只是有点希望。但是考虑到互联网上没有任何关于如何拖动 OS X 控件的其他信息(有几个博客和信息关于如何拖动图像 - 但即使是那些更像是拖放在视图周围的 swift 中键入解决方案)这是一个有效的解决方案。我相信有经验的 OS X Xcode 大师可以改进这个解决方案 - 如果有经验的 OS X 开发人员希望做出贡献,我欢迎对此解决方案进行改进。
感谢您的代码!它帮助了我。
我遇到了你说的同样的问题,移动的元素反弹。 我怀疑这是因为 mouseDragged 被调用了几次,并且你得到了一个原始位置,当计算新位置时,它可能已经发生了变化。
我重建移动方法,使用单行(以避免 mouseDragged 调用之间的冲突)并在调用 mouseDown 时使用元素位置。
当然这不是最好的方法,它只是消除弹跳问题的替代方法。
override func mouseDragged(with event: NSEvent) {
let dragPoint = event.locationInWindow
if controlToMove != nil {
controlToMove!.setFrameOrigin(NSPoint(x: (lastLocation?.x)! + (dragPoint.x - (mouseDownLocation?.x)!), y: (lastLocation?.y)! + (dragPoint.y - (mouseDownLocation?.y)!)));
}
}
希望对您有所帮助!