Как переместить NSImageView внутри NSView в Какао?

В моем приложении Mac OS мне нужна функциональность, чтобы иметь возможность перемещать NSImageView внутри NSView после того, как событие mouseDown (инициированное пользователем) происходит в этом NSImageView. Когда пользователь запускает событие мыши Up, это представление должно переместиться в направлении последнего события mouseDrag и остаться там. Во время перемещения я хочу, чтобы NSImageView был виден на экране (он должен двигаться вместе с курсором мыши).

Я прочитал руководство Apple по обработке событий мыши, https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html Также я скачал этот пример кода: https://developer.apple.com/library/content/samplecode/DragItemAround/Introduction/Intro.html

Обе ссылки содержат код в Objective C. Код для DragItemAround устарел. Я пытался найти решения на GitHub и других потоках Stackru, но не нашел никаких рабочих решений.

Был бы рад услышать ответы на этот вопрос. Я использую Swift 3.

Я создал собственный MovableImageView, который является подклассом NSImageView с этим кодом:

import Cocoa

class MovableImageView: NSImageView {

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        // Drawing code here.
        // setup the starting location of the
        // draggable item

    }

    override func mouseDown(with event: NSEvent) {
        Swift.print("mouseDown")

        //let window = self.window!
        //let startingPoint = event.locationInWindow


    }


    override func mouseDragged(with event: NSEvent) {
        Swift.print("mouseDragged")

        self.backgroundColor = NSColor.black

    }

    override func mouseUp(with event: NSEvent) {
        Swift.print("mouseUp")
    }

}

После этого в Интерфейсном Разработчике я установил этот класс в NSImageView. Я также установил ограничения в Интерфейсном Разработчике для этого NSImageView.

Теперь я пытаюсь выяснить, как переместить NSImageView внутри NSView? (Swift 3, XCode 8)

3 ответа

Решение

Вам нужно сохранить точку mouseDown и использовать ее для смещения позже. Пожалуйста, проверьте следующий код:

class MovableImageView: NSImageView {

var firstMouseDownPoint: NSPoint = NSZeroPoint

init() {
    super.init(frame: NSZeroRect)
    self.wantsLayer = true
    self.layer?.backgroundColor = NSColor.red.cgColor
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)

    // Drawing code here.
}

override func mouseDown(with event: NSEvent) {
    Swift.print("mouseDown")
    firstMouseDownPoint = (self.window?.contentView?.convert(event.locationInWindow, to: self))!
}

override func mouseDragged(with event: NSEvent) {
    Swift.print("mouseDragged")
    let newPoint = (self.window?.contentView?.convert(event.locationInWindow, to: self))!
    let offset = NSPoint(x: newPoint.x - firstMouseDownPoint.x, y: newPoint.y - firstMouseDownPoint.y)
    let origin = self.frame.origin
    let size = self.frame.size
    self.frame = NSRect(x: origin.x + offset.x, y: origin.y + offset.y, width: size.width, height: size.height)
}

override func mouseUp(with event: NSEvent) {
    Swift.print("mouseUp")

    }
}

В родительском представлении просто добавьте этот MovableImageView как подпредставление следующим образом:

let view = MovableImageView()
view.frame = NSRect(x: 0, y: 0, width: 100, height: 100)
self.view.addSubview(view) //Self is your parent view

Ограниченная версия ответа @brianLikeApple:

      class MovableImageView: NSImageView {

var firstMouseDownPoint: NSPoint = NSZeroPoint
var xConstraint: NSLayoutConstraint!
var yContstraint: NSLayoutConstraint!

required init?(coder aDecoder: NSCoder) {
   super.init(coder: aDecoder)
    self.wantsLayer = true
    self.layer?.backgroundColor = NSColor.red.cgColor
}
override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)
    
    // Drawing code here.
}

override func mouseDown(with event: NSEvent) {
    Swift.print("mouseDown")
    firstMouseDownPoint = (self.window?.contentView?.convert(event.locationInWindow, to: self))!
}

override func mouseDragged(with event: NSEvent) {
    Swift.print("mouseDragged")
    let newPoint = (self.window?.contentView?.convert(event.locationInWindow, to: self))!
    let offset = NSPoint(x: newPoint.x - firstMouseDownPoint.x, y: newPoint.y - firstMouseDownPoint.y)
    let origin = self.frame.origin
    let size = self.frame.size
    yContstraint.constant = (self.superview?.frame.height)! - origin.y - offset.y - size.height
    xConstraint.constant = origin.x + offset.x
}

override func mouseUp(with event: NSEvent) {
    Swift.print("mouseUp")
    
}

Вот NSView, который вы можете перетащить. Он использует ограничения точно так же, как ответ @ExeRhythm.

      import AppKit
class DraggableNSView: NSView {
    var down: NSPoint = NSZeroPoint
    @IBOutlet var across: NSLayoutConstraint!
    @IBOutlet var up: NSLayoutConstraint!

    override func mouseDown(with e: NSEvent) {
        down = window?.contentView?.convert(e.locationInWindow, to: self) ?? NSZeroPoint
    }

    override func mouseDragged(with e: NSEvent) {
        guard let m = window?.contentView?.convert(e.locationInWindow, to: self) else { return }
        let p = frame.origin + (m - down)
        across.constant = p.x
        up.constant = p.y
    }
}

Не забывайте, что вы должны подключить acrossа также upограничения в раскадровке!

Примечание. Если вы предпочитаете ограничение «вниз», а не «вверх», это:

              // if you prefer a "down" constraint:
        down.constant = (superview?.frame.height)! - p.y - frame.size.height

Как всегда, добавьте эти две функции в свой проект,

      func -(lhs: CGPoint, rhs: CGPoint) -> CGPoint {
    return CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}

func +(lhs: CGPoint, rhs: CGPoint) -> CGPoint {
    return CGPoint(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}

Обратите внимание, что вы, конечно, можете сделать это для любого подкласса NSView, такого как NSImageView:

      class DraggableNSImageView: NSView {
     ... same
Другие вопросы по тегам