如何将Swift UI视图转换为NSImage

问题描述 投票:0回答:1

我正在尝试将SwiftUI视图用作MacOS上的NSCursor。

使用SwiftUI,我正在构建一个视图,然后使用NSHostingView将该视图转换为NSView。现在,我尝试通过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文件获得了鼠标光标。

执行上面显示的代码时,我总是得到一个大小为480x480的空鼠标光标。在调试模式下,我可以看到myNSView是一个空png。我敢肯定,我会误解文档,因此会滥用cacheDisplay(in:to:)bitmapImageRepForCachingDisplay(in:)documentation告诉我使用NSBitmapImageRepbitmapImageRepForCachingDisplay(in:)中的cacheDisplay(in:to:)。但是由于某种原因,我根本无法使它正常工作。

有人知道我在做什么错吗?

swift macos swiftui appkit
1个回答
0
投票

回答我自己的问题:

[似乎需要将视图转换为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 -----注释之间的行已更改,这是可行的解决方案。我只是在应用与以前相同的方法之前将视图嵌入窗口中。希望这对以后的人们有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.