2012-01-04 119 views
0

我想實現一個自定義的圓形滑塊,它使用圖像繪製撥號和旋鈕。爲此,我已將子類別NSSliderCell並覆蓋了drawBarInsidedrawKnob方法。 現在,如果我將滑塊類型保留爲默認(水平),則會調用繪圖函數並繪製圖像而不是默認的條形圖和旋鈕(當然由於圖像是爲圓形滑塊創建的,在那兒)。但是,只要我將滑塊類型更改爲循環(在IB中或通過在滑塊單元中設置self.sliderType = NSCircularSlider;),這兩種方法都不會被調用,並且我的圖像也不會繪製(僅創建標準撥號)。 我在這裏忘了什麼,或者可以不定製圓形滑塊嗎?自定義圓形NSSlider

這裏是我的代碼: DialSliderCellNSSliderCell子類,並開始在一個名爲DialSlider類是NSSlider一個子集(這個類沒有別的當時)。

@implementation DialSliderCell 

- (id)init { 
    self = [super init]; 
    if (self) { 
     dialImage = [NSImage imageNamed:@"dial"]; 
     knobImage = [NSImage imageNamed:@"dialKnob"]; 
     self.sliderType = NSCircularSlider; 
    } 
    NSLog(@"init"); 
    return self; 
} 

- (void)drawKnob:(NSRect)knobRect { 
    knobRect.size = knobImage.size; 
    [knobImage drawInRect:knobRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; 
    NSLog(@"drawKnob"); 
} 

- (void)drawBarInside:(NSRect)aRect flipped:(BOOL)flipped { 
    [dialImage drawInRect:aRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; 
    NSLog(@"drawBarInside"); 
} 

@end 
+0

只是一個短信給任何人複製該代碼:這是隻有使用ARC時纔是正確的。否則,當您將它們放入dialImage/knobImage實例變量中時,您需要保留從-imageNamed獲得的圖像。 – uliwitness 2012-08-13 12:30:42

+0

正確。該代碼是在ARC環境下編寫的,因此不保留/釋放。 – pajevic 2012-08-13 15:40:49

回答

2

我已經通過覆蓋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]; 
} 
+0

太好了,謝謝。我注意到圖像是顛倒的,因此您需要使用'drawInRect:fromRect:operation:fraction:respectFlipped:hints:'以正確的方向顯示圖像。 – VinceFior 2015-07-14 06:08:46

+0

此外,*如果您將應用程序提交到App Store,則無法設置_trackRect *,因爲顯然將該屬性設置爲使用私有API。 – VinceFior 2015-08-01 04:34:06

0

所有我能想到的是,你不重寫所有指定initialisers

從文檔...

指定初始化。當繼承NSCell時,您必須實現指定初始化程序的所有 。這些方法是:init, initWithCoder:,initTextCell:和initImageCell :.

可能是其他3個之一被稱爲圓形滑塊。

+0

嗨沃倫。其實我是,但爲了簡單起見,我決定不在這裏包括它們。無論如何,正如我所說的,'DialSliderCell'是在'DialSlider'手動創建的,所以我很確定哪個init方法正在使用:)但是如果我在IB中設置滑動單元的類,那麼它使用'initWithCoder'對我的問題沒有什麼不同。 – pajevic 2012-01-04 08:30:54

+0

當您的滑塊從XIB中取消存檔時,它將取消存檔視圖和單元格。這意味着要使用正確的單元類,您需要雙擊XIB中的視圖,以便選擇NSSliderCell並設置其自定義類,而不僅僅是NSSlider視圖。你在做那個嗎? – uliwitness 2012-08-13 12:29:08