在 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)!)));

        }
    }

希望对您有所帮助!