【问题标题】:Setting IB content filter for NSProgressIndicator color为 NSProgressIndicator 颜色设置 IB 内容过滤器
【发布时间】:2021-08-17 11:45:22
【问题描述】:

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

我已阅读 this post,其中谈到了以编程方式修改 NSProgressIndicator。

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

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

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

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

另一篇文章提到设置 .appearance,但这将我引向 this repository ,这似乎不是我想要的。我愿意做我的功课并弄清楚这一点,但我会空手而归,使用 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

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

【问题讨论】:

  • 我弄清楚了闪烁的来源。在我的测试中,我在设置 redFilter progressBar.contentFilter = []; progressBar.contentFilter = [redFilter] 之前有一条线,然后当我将 progressBar 重置为 darkGreenFilter progressBar.contentFilter = []; progressBar.contentFilter = [darkGreenFilter] 时,我删除了这些线后闪烁消失了。对我好!

标签: swift nsprogressindicator


【解决方案1】:

回到这个话题。这是我的答案

Swift 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
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-10-08
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 2015-09-19
    相关资源
    最近更新 更多