首页 > 解决方案 > 为 NSProgressIndicator 颜色设置 IB 内容过滤器

问题描述

我在这里搜索了谷歌、Apple 文档、gitHub 等,找不到任何关于如何使用内容过滤器来设置 NSProgressIndicator 的颜色的信息。我想在 macOS 中执行此操作。

我读过这篇关于以编程方式修改 NSProgressIndicator 的帖子。

但是,我在 IB 的 NSProgressIndicator 上设置了一个内容过滤器,即 False Color。它有两种颜色,颜色 1 和颜色 2。我将颜色 1 设置为绿色,将颜色 2 设置为红色。

通过将内容过滤器、假色、颜色 1 设置为自定义绿色,我的 NSProgressIndicator 现在默认为绿色。因此,这告诉我它正在从我的内容过滤器颜色 1 中提取该颜色,但我不知道它是如何做到的。

如何以编程方式将 NSProgressIndicator 的颜色设置为内容过滤器颜色 2?

我会发布有关如何处理此问题的代码,但我什至不知道如何开始。

另一篇文章提到设置 .appearance,但这将我带到了这个存储库,这似乎不是我想要的。我愿意做我的功课并弄清楚这一点,但我会空手而归,使用 IB 中设置的内容过滤器。

编辑 1:经过进一步调查,如果我执行 print(progressBar.contentFilters) 我可以看到在 IB 的内容过滤器中设置的两种颜色,假色设置。这是打印输出:

[<CIFalseColor: 0x6000026039c0>
inputImage=nil
inputColor0=<CIColor 0x600000cc4570 (0 0.976805 0 1) devicergb>
inputColor1=<CIColor 0x600000cc45d0 (1 0.149131 0 1) devicergb>
]

所以现在的问题是,如何让progressBar 使用定义为inputColor1 的颜色?

编辑2: 所以,在搞砸了几个小时之后,我现在能够得到一个中途工作的解决方案。我说一半是因为对 progress.contentFilters = [Filter Name] 的调用会导致完整的窗口刷新,在 viewDidLoad 方法中应用第一个 darkGreen 过滤器后看起来像一个明亮的单次闪烁(初始设置没有闪烁)筛选)。

@IBOutlet weak var progressBar: NSProgressIndicator!

// Set the filter properties
let darkGreenFilter = CIFilter(name: "CIFalseColor")!
let redFilter = CIFilter(name: "CIFalseColor")!
// Set the CIColors for the two filters
let darkGreenCIColor = CIColor(red: 0, green: 0.6, blue: 0.4, alpha: 1)
let redCIColor = CIColor(red: 1, green: 0, blue: 0, alpha: 1)
// Set a boolean flag that the progressBar color was changed
var progressBarColorChanged = false

然后在viewDidLoad中:

// Set the values for the filters
darkGreenFilter.setValue(darkGreenCIColor, forKey: "inputColor0")
redFilter.setValue(redCIColor, forKey: "inputColor0")
// Set the progress indicator to dark green
progressBar.contentFilters = [darkGreenFilter]
// Set the progress to zero (removes the colored bar)
progressBar.doubleValue = 0

然后在后面监控progressBar状态的方法中

if progressBar.doubleValue > 0.75 && !progressBarColorChanged {
    progressBar.contentFilters = [redFilter]
    progressBarColorChanged = true
}

然后一旦执行完成,我使用重置方法将其全部放回

progressBar.contentFilter = [darkGreen]
progressBar.doubleValue = 0
progressBarColorChanged = false

我正在慢慢到达那里。有人对如何更好地做到这一点有任何建议,或者我如何消除讨厌的屏幕闪烁?

标签: swiftnsprogressindicator

解决方案


回到这个。这是我的答案

斯威夫特 5.4 / macOS

import Cocoa

class ViewController: NSViewController {

    let greenFilter = CIFilter(name: "CIFalseColor")!
    let greenCIColor = CIColor(red: 0.3333, green: 0.8667, blue: 0.0, alpha: 1.0)
    let darkGreenCIColor = CIColor(red: 0, green: 0.5373, blue: 0.1137, alpha: 1.0)
    let redFilter = CIFilter(name: "CIFalseColor")!
    let redCIColor = CIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
    let darkRedCIColor = CIColor(red: 0.6275, green: 0.0, blue: 0.0078, alpha: 1.0)
    var redFilterColorChange = false
    var progressBar: NSProgressIndicator?
    var timer = Timer()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let progressFrame = NSRect(x: view.frame.midX-view.frame.width/2+30, y: view.frame.midY-10, width: view.frame.width-60, height: 20)
        progressBar = NSProgressIndicator(frame: progressFrame)
        self.view.addSubview(progressBar!)
        progressBar?.contentFilters = []
        if NSApp.effectiveAppearance.name == .darkAqua {
            greenFilter.setValue(darkGreenCIColor, forKey: "inputColor0")
            redFilter.setValue(darkRedCIColor, forKey: "inputColor0")
        } else {
            greenFilter.setValue(greenCIColor, forKey: "inputColor0")
            redFilter.setValue(redCIColor, forKey: "inputColor0")
        }
        // Apply the filter
        progressBar?.contentFilters = [greenFilter]
        progressBar?.isHidden = false
        progressBar?.isIndeterminate = false
        progressBar?.doubleValue = 0
        progressBar?.maxValue = 1.0
        startTimer()
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

    func startTimer() {
        print("Starting timer")
        timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateProgress), userInfo: nil, repeats: true)
        print("Progress bar frame = \(progressBar!.frame)")
    }

    @objc func updateProgress() {
        if progressBar!.doubleValue < 1.0 {
            if progressBar!.doubleValue > 0.75 && !redFilterColorChange {
                progressBar?.contentFilters = [redFilter]
                redFilterColorChange = true
            }
            progressBar?.doubleValue += 0.01
            print("Progress bar value = \(progressBar!.doubleValue)")
        } else {
            timer.invalidate()
            progressBar?.contentFilters = [greenFilter]
            progressBar?.doubleValue = 0
            progressBar?.isHidden = true
        }
    }
}

推荐阅读