簡體   English   中英

更改 NSSlider 欄顏色

[英]Change NSSlider bar color

我有一個 NSWindow 和一個水平的 NSSlider。

當窗口背景顏色更改時,我想更改滑塊右側部分的顏色。

在此處輸入圖片說明

在此處輸入圖片說明

目前,當窗口背景變暗時,欄的右側部分不再可見。

注意:窗口背景實際上是我通過覆蓋窗口視圖子類中的drawRect繪制的漸變。

我以為我可以通過NSSliderCell並覆蓋一些方法(如drawBarInside來更改滑塊欄填充顏色,但我不明白它是如何工作的:我應該制作一個小方形圖像並在旋鈕后的矩形中重復繪制它嗎? 或者也許只是畫一條彩色線? 我以前從未這樣做過。

我看過這個問題,這很有趣,但它是關於繪制旋鈕的,我現在不需要它。

我也看過這個看起來很有前途的,但是當我嘗試模仿這段代碼時,我的滑塊消失了......

這個問題中,他們使用drawWithFrame並且看起來很有趣,但我不確定它是如何工作的。

我想用我自己的代碼而不是使用庫來做到這一點。 有人可以給我一個關於如何做到這一點的提示嗎? :)

我正在 Swift 中執行此操作,但如有必要,我可以閱讀/使用 Objective-C。

首先,我創建了一個滑動條的圖像並將其復制到我的項目中。

然后我在drawBarInside方法中使用此圖像在正常的rect之前繪制rect ,因此我們將只看到剩余部分(我想保持藍色部分完整無缺)。

這必須在NSSliderCell的子類中NSSliderCell

class CustomSliderCell: NSSliderCell {

    let bar: NSImage

    required init(coder aDecoder: NSCoder) {
        self.bar = NSImage(named: "bar")!
        super.init(coder: aDecoder)
    }

    override func drawBarInside(aRect: NSRect, flipped: Bool) {
        var rect = aRect
        rect.size = NSSize(width: rect.width, height: 3)
        self.bar.drawInRect(rect)
        super.drawBarInside(rect, flipped: flipped)
    }

}

親:它有效。 :)

缺點:它刪除了條形的圓邊,我還沒有找到重新繪制它的方法。

自定義 nsslider

更新:

我制作了一個已接受答案的 Swift 版本,效果很好:

class CustomSliderCell: NSSliderCell {

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func drawBarInside(aRect: NSRect, flipped: Bool) {
        var rect = aRect
        rect.size.height = CGFloat(5)
        let barRadius = CGFloat(2.5)
        let value = CGFloat((self.doubleValue - self.minValue) / (self.maxValue - self.minValue))
        let finalWidth = CGFloat(value * (self.controlView!.frame.size.width - 8))
        var leftRect = rect
        leftRect.size.width = finalWidth
        let bg = NSBezierPath(roundedRect: rect, xRadius: barRadius, yRadius: barRadius)
        NSColor.orangeColor().setFill()
        bg.fill()
        let active = NSBezierPath(roundedRect: leftRect, xRadius: barRadius, yRadius: barRadius)
        NSColor.purpleColor().setFill()
        active.fill()
    }

}

這是正確的,你必須繼承的NSSliderCell重繪棒旋鈕

NSRect只是一個矩形容器,你必須在這個容器內繪制。 我根據我的一個程序中的自定義NSLevelIndicator制作了一個示例。

首先,您需要計算旋鈕的位置。 您必須注意控制最小值和最大值。 接下來,您為背景繪制一個NSBezierPath ,為左側部分繪制另一個。

自定義 NSSlider 控制欄

#import "MyCustomSlider.h"

@implementation MyCustomSlider

- (void)drawBarInside:(NSRect)rect flipped:(BOOL)flipped {

//  [super drawBarInside:rect flipped:flipped];

    rect.size.height = 5.0;

    // Bar radius
    CGFloat barRadius = 2.5;

    // Knob position depending on control min/max value and current control value.
    CGFloat value = ([self doubleValue]  - [self minValue]) / ([self maxValue] - [self minValue]);

    // Final Left Part Width
    CGFloat finalWidth = value * ([[self controlView] frame].size.width - 8);

    // Left Part Rect
    NSRect leftRect = rect;
    leftRect.size.width = finalWidth;

    NSLog(@"- Current Rect:%@ \n- Value:%f \n- Final Width:%f", NSStringFromRect(rect), value, finalWidth);

    // Draw Left Part
    NSBezierPath* bg = [NSBezierPath bezierPathWithRoundedRect: rect xRadius: barRadius yRadius: barRadius];
    [NSColor.orangeColor setFill];
    [bg fill];

    // Draw Right Part
    NSBezierPath* active = [NSBezierPath bezierPathWithRoundedRect: leftRect xRadius: barRadius yRadius: barRadius];
    [NSColor.purpleColor setFill];
    [active fill];


}

@end

斯威夫特 5

class CustomSliderCell: NSSliderCell {
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func drawBar(inside aRect: NSRect, flipped: Bool) {
        var rect = aRect
        rect.size.height = CGFloat(5)
        let barRadius = CGFloat(2.5)
        let value = CGFloat((self.doubleValue - self.minValue) / (self.maxValue - self.minValue))
        let finalWidth = CGFloat(value * (self.controlView!.frame.size.width - 8))
        var leftRect = rect
        leftRect.size.width = finalWidth
        let bg = NSBezierPath(roundedRect: rect, xRadius: barRadius, yRadius: barRadius)
        NSColor.orange.setFill()
        bg.fill()
        let active = NSBezierPath(roundedRect: leftRect, xRadius: barRadius, yRadius: barRadius)
        NSColor.purple.setFill()
        active.fill()
    }
}

我完全沒有重繪或覆蓋單元格就實現了這一點。 使用“假色”過濾器似乎效果很好,而且只有幾個代碼!

class RLSlider: NSSlider {
init() {
    super.init(frame: NSZeroRect)
    addFilter()
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    addFilter()
}

func addFilter() {
    let colorFilter = CIFilter(name: "CIFalseColor")!
    colorFilter.setDefaults()
    colorFilter.setValue(CIColor(cgColor: NSColor.white.cgColor), forKey: "inputColor0")
    colorFilter.setValue(CIColor(cgColor: NSColor.yellow.cgColor), forKey: "inputColor1")

//        colorFilter.setValue(CIColor(cgColor: NSColor.yellow.cgColor), forKey: "inputColor0")
//        colorFilter.setValue(CIColor(cgColor: NSColor.yellow.cgColor), forKey: "inputColor1")

    self.contentFilters = [colorFilter]
}
}

在此處輸入圖片說明

暫無
暫無

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

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