Как преобразовать представление Swift UI в NSImage - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь использовать представление SwiftUI в качестве NSCursor в MacOS.

Используя SwiftUI, я создаю представление, которое затем преобразовываю в NSView с использованием NSHostingView. Теперь я пытаюсь преобразовать это в NSImage через NSBitmapImageRep. По какой-то причине я всегда получаю пустой png при проверке переменных во время установки точек останова.

(На данный момент настройка курсора выполняется в AppDelegate, потому что в данный момент я просто пытаюсь заставить это работать.)

class AppDelegate: NSObject, NSApplicationDelegate {

    var window: NSWindow!


    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()
        let contentRect = NSRect(x: 0, y: 0, width: 480, height: 480)

        // Create the window and set the content view. 
        window = NSWindow(
            contentRect: contentRect,
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)

        let myNSView = NSHostingView(rootView: ContentView()).bitmapImageRepForCachingDisplay(in: contentRect)!

        NSHostingView(rootView: ContentView()).cacheDisplay(in: contentRect, to: myNSView)

        let myNSImage = NSImage(size: myNSView.size)
        myNSImage.addRepresentation(myNSView)

        self.window.disableCursorRects()

//        var myName = NSImage.Name("ColorRing")
//        var myCursorImg = NSImage(named: myName)!
//
//        var myCursor = NSCursor(image: myCursorImg, hotSpot: NSPoint(x: 10, y: 10))


        var myCursor = NSCursor(image: myNSImage, hotSpot: NSPoint(x: 0, y: 0))
        myCursor.set()
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }


}

При выполнении закомментированной части я получаю курсор мыши из внешнего png-файла.

При выполнении кода, показанного выше, я всегда получаю пустой курсор мышис размером 480х480. В режиме отладки я вижу, что myNSView - пустой png. Я почти уверен, что неправильно понял документацию и поэтому неправильно использую cacheDisplay(in:to:) и bitmapImageRepForCachingDisplay(in:). Документация говорит мне использовать NSBitmapImageRep с bitmapImageRepForCachingDisplay(in:) в cacheDisplay(in:to:). Но по какой-то причине я просто не могу заставить это работать.

Кто-нибудь имеет представление, что я делаю неправильно?

1 Ответ

0 голосов
/ 08 ноября 2019

Чтобы ответить на мой собственный вопрос:

Кажется, что представление, которое нужно преобразовать в NSImage, должно быть выложено внутри окна. В противном случае он, вероятно, не знает, насколько большим должно быть представление внутри прямоугольника.

У меня работает следующий код:

func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()
        let contentRect = NSRect(x: 0, y: 0, width: 480, height: 480)

        // Create the window and set the content view. 
        window = NSWindow(
            contentRect: contentRect,
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)

        // CHANGED ----------
        let newWindow = NSWindow(
            contentRect: contentRect,
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)

        newWindow.contentView = NSHostingView(rootView: contentView)

        let myNSBitMapRep = newWindow.contentView!.bitmapImageRepForCachingDisplay(in: contentRect)!

        newWindow.contentView!.cacheDisplay(in: contentRect, to: myNSBitMapRep)
        // CHANGED ----------

        let myNSImage = NSImage(size: myNSBitMapRep.size)
        myNSImage.addRepresentation(myNSBitMapRep)

        self.window.disableCursorRects()

        var myCursor = NSCursor(image: myNSImage, hotSpot: NSPoint(x: 0, y: 0))
        myCursor.set()
}

Были только строки между двумя //CHANGED ----- комментариями. поменял на рабочий раствор. Я просто встраиваю вид в окно перед применением тех же методов, что и раньше. Надеюсь, что это поможет некоторым людям в будущем.

...