swift 更改NSSlider条颜色

hzbexzde  于 2023-03-22  发布在  Swift
关注(0)|答案(4)|浏览(264)

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

当窗口背景色改变时,我想改变滑动条右边部分的颜色。

目前,当窗口背景变暗时,栏的右侧部分不再可见。

  • 注意:窗口背景实际上是我通过覆盖窗口视图子类中的drawRect绘制的渐变。*

我想我可以通过子类化NSSliderCell并覆盖一些方法(如drawBarInside)来更改滑块填充颜色,但我不明白它是如何工作的:我应该做一个小的正方形图像,然后在旋钮后面的矩形中反复绘制它吗?或者只是画一条彩色线?我以前从来没有这样做过。
我看过this question,它很有趣,但它是关于绘制旋钮的,我现在不需要它。
我还看了看this one,它看起来很有前途,但是当我试图模仿这个代码时,我的滑动条就消失了...
this question中,他们使用drawWithFrame,它看起来很有趣,但我不确定它是如何工作的。
我想用我自己的代码来做这件事,而不是使用库。有人能给予我一个关于如何做到这一点的提示吗?:)

  • 我在Swift中完成此操作,但如果需要,我可以阅读/使用Objective-C。*
uttx8gqw

uttx8gqw1#

首先,我创建了一个滑动条的图像,并将其复制到我的项目中。
然后,我在drawBarInside方法中使用此图像,在普通条 * 之前绘制rect *,因此我们将只看到剩余部分(我想保持蓝色部分不变)。
这必须在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)
    }

}

Pro:它起作用了。:)
缺点:它删除了酒吧的圆形边缘,我还没有找到一种方法来重新绘制这一点。

更新日期:

我做了一个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()
    }

}
qnakjoqk

qnakjoqk2#

这是正确的,您必须子类化NSSliderCell类来重绘条形图旋钮
NSRect只是一个矩形容器,你必须在这个容器中绘制。我在一个程序中基于自定义的NSLevelIndicator做了一个例子。
首先你需要计算旋钮的位置。你必须注意控制的最小值和最大值。接下来你画一个NSBezierPath作为背景,另一个作为左边部分。

#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 background track
    NSBezierPath* bg = [NSBezierPath bezierPathWithRoundedRect: rect xRadius: barRadius yRadius: barRadius];
    [NSColor.orangeColor setFill];
    [bg fill];

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

}

@end
jckbn6z7

jckbn6z73#

雨燕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()
    }
}
pgpifvop

pgpifvop4#

我已经实现了这一点没有重绘或覆盖细胞在所有。使用“假色”过滤器似乎工作得很好,它只是几个代码!

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

相关问题