Objective c 自定义圆形滑块

Objective c 自定义圆形滑块,objective-c,macos,cocoa,Objective C,Macos,Cocoa,我试图实现一个自定义的圆形滑块,它使用图像来绘制刻度盘和旋钮。为此,我对NSSliderCell进行了子类化,并覆盖了trabrinside和drawKnob方法。 现在,如果我将滑块类型保留为默认值(水平),将调用我的绘图函数,并绘制图像,而不是默认的条形图和旋钮(当然,这看起来完全错误,因为图像是为圆形滑块制作的,但它们确实存在)。但一旦我将滑块类型更改为圆形(在IB中或通过在我的滑块单元格中设置self.sliderType=NSCircularSlider;),这两种方法就不会被调用,也

我试图实现一个自定义的圆形滑块,它使用图像来绘制刻度盘和旋钮。为此,我对
NSSliderCell
进行了子类化,并覆盖了
trabrinside
drawKnob
方法。 现在,如果我将滑块类型保留为默认值(水平),将调用我的绘图函数,并绘制图像,而不是默认的条形图和旋钮(当然,这看起来完全错误,因为图像是为圆形滑块制作的,但它们确实存在)。但一旦我将滑块类型更改为圆形(在IB中或通过在我的滑块单元格中设置
self.sliderType=NSCircularSlider;
),这两种方法就不会被调用,也不会绘制图像(只创建标准刻度盘)。 我是不是忘了什么,或者圆形滑块根本就不能定制

这是我的密码:
DialSliderCell
NSSliderCell
的子类,在名为
DialSlider
的类中启动和设置,该类是
NSSlider
的子类(该类当时不做任何其他事情)


我所能想到的是,您没有覆盖所有指定的初始值设定项

从文件中

指定的初始化者。当子类化NSCell时,必须实现所有 指定的初始值设定人。这些方法是:init, initWithCoder:、initTextCell:、initImageCell:


其他3种方法中可能有一种被称为圆形滑块。

我通过覆盖
drawInteriorWithFrame
方法解决了这个问题。该解决方案基于原始方法。我只是删除了与圆形滑块无关的任何内容,删除了原始图形并添加了我自己的图形。几何图形几乎完全是原始的

- (void) drawInteriorWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
{
    cellFrame = [self drawingRectForBounds: cellFrame];
    _trackRect = cellFrame;

    NSPoint knobCenter;
    NSPoint point;
    float fraction, angle, radius;

    knobCenter = NSMakePoint(NSMidX(cellFrame), NSMidY(cellFrame));

    [dialImage drawInRect:cellFrame fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];

    int knobDiameter = knobImage.size.width;
    int knobRadius = knobDiameter / 2;
    fraction = ([self floatValue] - [self minValue]) / ([self maxValue] - [self minValue]);
    angle = (fraction * (2.0 * M_PI)) - (M_PI / 2.0);
    radius = (cellFrame.size.height / 2) - knobDiameter;
    point = NSMakePoint((radius * cos(angle)) + knobCenter.x,
                    (radius * sin(angle)) + knobCenter.y);

    NSRect dotRect;
    dotRect.origin.x = point.x - knobRadius;
    dotRect.origin.y = point.y - knobRadius;
    dotRect.size = knobImage.size;
    [knobImage drawInRect:dotRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
}
cellFrame
矩形的大小设置为
dialImage
图像的大小

请注意,上面的方法似乎没有自动调用,因此我还必须重写
drawWithFrame
方法,并使其调用
drawInteriorWithFrame

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    [self drawInteriorWithFrame:cellFrame inView:controlView];
}

你好,沃伦。实际上我是,但为了简单起见,我选择不在这里包含它们。无论如何,正如我所说的,
DialSliderCell
是在
DialSlider
中手动创建的,所以我很确定使用的是哪个init方法:)但是如果我在IB中设置滑块单元格的类,那么它使用的是
initWithCoder
,这对我的问题没有影响。当滑块从XIB中未归档时,它取消了视图和单元格的归档。这意味着要使其使用正确的单元类,您需要双击XIB中的视图,以便它选择NSSliderCell并设置其自定义类,而不仅仅是NSSlider视图的自定义类。你在这么做吗?请给复制此代码的人一个简短的提示:这仅在使用ARC时才正确。否则,当您将图像放入dialImage/knobImage实例variables.Correct时,您需要保留从-imageNamed:获得的图像。代码是在ARC环境中编写的,因此没有保留/发布。太好了,谢谢。我注意到图像绘制颠倒,因此您需要使用
drawInRect:fromRect:operation:fraction:reservitflipped:hints:
以正确的方向显示图像。此外,如果您将应用提交到应用商店,则无法设置_trackRect,因为设置该属性显然被视为使用私有API。
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    [self drawInteriorWithFrame:cellFrame inView:controlView];
}