簡體   English   中英

渲染錯誤? 將透明 NSWindow 與 SwiftUI 用於 MacOS 應用程序時

[英]Rendering bug? when using transparent NSWindow with SwiftUI for MacOS app

我正在使用 SwiftUI(來自 XCode 14.1 的最新版本)開發一個 macOS 應用程序,應用程序設置如下

import SwiftUI

@main
struct DemoApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate

    var body: some Scene {
        Window("demo", id: "demo") {
            ContentView()
        }.windowStyle(.hiddenTitleBar)
    }
}

class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
    @Published var active: Bool = true

    var mainWindow: NSWindow? {
        for w in NSApplication.shared.windows {
            if w.title == "demo" {
                return w
            }
        }
        return nil
    }

    private func setupMainWindow() {
        
    }

    @MainActor func applicationDidFinishLaunching(_: Notification) {
        guard let w = mainWindow else {
            print("nothing to setup")
            return
        }

        w.level = .floating
        w.backgroundColor = NSColor.clear
        w.isOpaque = false
        w.standardWindowButton(.zoomButton)?.isHidden = true
        w.standardWindowButton(.closeButton)?.isHidden = true
        w.standardWindowButton(.miniaturizeButton)?.isHidden = true
    }
}

內容視圖定義如下

import SwiftUI

struct ContentView: View {
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    
    @State var counter = 0

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world! \(counter)").font(.system(size: 20).monospaced())
        }
        .padding().onReceive(timer) { _ in
            counter += 1
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

基本上這個應用程序所做的是渲染一個透明的背景 window,上面有一些內容。 內容有一張 static 圖像和每秒更新一次的文本(帶有計數器)。

window 的初始渲染看起來不錯,但是一旦內容開始更新,就會渲染兩個重復的工件:一個來自第一個渲染結果,第二個來自最新的渲染結果。 第二個重疊在第一個之上。

這是在深色背景(另一個窗口)上渲染的 window 的屏幕截圖:

這是在白色背景(另一個窗口)上呈現的 window 的屏幕截圖:

在我看來,當 window 最初啟動時,因為它是透明的,不知何故操作系統或框架正在向渲染內容添加一些輪廓,正如您從“Hello world 0”字符串中看到的那樣,那里有一個輪廓。 也許框架正在嘗試做一些事情來將 window 內容與它下面的其他內容區分開來?

當 window 開始更新內容時,會重新繪制新內容,但最初捕獲的輪廓仍然存在,留下這個與當前渲染內容不匹配的奇怪工件。

我試圖禁用透明 window(具有純色背景或具有非零 alpha 的背景)。 這將完全消除問題。 添加的輪廓只有在 window 完全透明時才能看到。 據我所知,它與透明 window 背景和添加到內容中的輪廓有關。

更新:使用 hasShadow=false 不會完全移除邊框(頂部在黑色背景上仍然可見)。 查看頂部邊框

我正在以稍微不同的方式配置 window,不需要AppDelegate ,但我看到了同樣的事情。 backgroundColor.clear時,不僅渲染效果明顯,而且 window 也沒有邊框。

使用NSColor.white.withAlphaComponent(0.00001)作為backgroundColor消除了渲染問題,並且還正確顯示了邊框。

struct Mac_SwiftUI_testApp: App {
    var body: some Scene {
        
        Window("demo", id: "demo") {
            ContentView()
                .task {
                    NSApplication.shared.windows.forEach { window in
                        guard window.identifier?.rawValue == "demo" else { return  }
                        
                        window.standardWindowButton(.zoomButton)?.isHidden = true
                        window.standardWindowButton(.closeButton)?.isHidden = true
                        window.standardWindowButton(.miniaturizeButton)?.isHidden = true
                        window.backgroundColor = NSColor.white.withAlphaComponent(0.00001)
                        window.isOpaque = false
                        window.level = .floating
                    }
                }
        }
        .windowStyle(.hiddenTitleBar)
    }
}

backgroundColor =.clear

在此處輸入圖像描述

使用backgroundColor = NSColor.white.withAlphaComponent(0.00001)

在此處輸入圖像描述

在嘗試了一些事情之后,我發現設置

window.hasShadow = false

會解決你的問題。 它還刪除了清除 window 上的頂部“行”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM