2013-08-27 11 views
5

Mi piace creare una sottoclasse di NSProgressIndicator. Ho usato questo codice e ho impostato la sottoclasse in Interface Builder:Sottoclasse NSProgressIndicator

- (void)drawRect:(NSRect)dirtyRect { 
NSRect rect = NSInsetRect([self bounds], 1.0, 1.0); 
CGFloat radius = rect.size.height/2; 
NSBezierPath *bz = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius]; 
[bz setLineWidth:2.0]; 
[[NSColor blackColor] set]; 
[bz stroke]; 

rect = NSInsetRect(rect, 2.0, 2.0); 
radius = rect.size.height/2; 
bz = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius]; 
[bz setLineWidth:1.0]; 
[bz addClip]; 
rect.size.width = floor(rect.size.width * ([self doubleValue]/[self maxValue])); 
NSRectFill(rect); 

Quando l'applicazione inizia il suo aspetto come questo: App start

Ma durante la copia di avanzamento del vecchio bar si presenta. During copying

Cosa c'è di sbagliato?

+0

si è dimenticato di aggiungere [super drawRect: rect] –

+0

E 'non funziona con [super drawRect: rect]. – Konobi

+0

Quindi aggiungo NSLog alla mia sottoclasse e le chiamate alla sottoclasse solo una volta all'avvio, ma durante l'avanzamento della copia la classe non viene mai chiamata. – Konobi

risposta

2

Sembra che l'avanzamento della barra di avanzamento non sia stato disegnato in drawRect:, quindi basta ignorare drawRect: non è sufficiente. Tuttavia, se si esegue il backup della barra di avanzamento, si è responsabili di eseguire tutto il disegno.

Dal documentation:

classe di visualizzazione crea automaticamente uno strato di supporto per voi (utilizzando makeBackingLayer se ignorato), ed è necessario utilizzare meccanismi di disegno della classe View.

Controllare il "Layer Core Animation" in IB o aggiungere questo alla classe sub:

- (void)awakeFromNib { 
    [super awakeFromNib]; 
    [self setWantsLayer:YES]; 
} 
+0

Sì, ho dimenticato di impostare Core Animation Layer. Thx ... sry new to Cocoa non ho mai provato a sottoclasse prima; D – Konobi

1

ho seguito il consiglio di cui sopra (grazie), ma purtroppo scoperto che quando il NSProgressIndicator è stata ridimensionata, è scomparso, ma solo alla prima visione (era all'interno di un cassetto).

Piuttosto che cercare di capire cosa stava succedendo, mi sono reso conto che in realtà non hai bisogno del vecchio controllo, poiché ciò che stavo facendo è molto semplice (un indicatore di forza che cambia colore). Basta creare una sottoclasse di NSView.

Quindi questo è vero:

@interface SSStrengthIndicator : NSView 
/// Set the indicator based upon a score from 0..4 
@property (nonatomic) double strengthScore; 
@end 

@implementation SSStrengthIndicator 
- (void)setStrengthScore:(double)strength 
{ 
    if (_strengthScore != strength) { 
     _strengthScore = strength; 
     [self setNeedsDisplay:YES]; 
    } 
} 

- (void)drawRect:(NSRect)dirtyRect 
{ 
    NSRect rect = NSInsetRect([self bounds], 1.0, 2.0); 
    double val = (_strengthScore + 1) * 20; 
    if (val <= 40) 
     [[NSColor redColor] set]; 
    else if (val <= 60) 
     [[NSColor yellowColor] set]; 
    else 
     [[NSColor greenColor] set]; 

    rect.size.width = floor(rect.size.width * (val/100.0)); 
    [NSBezierPath fillRect:rect]; 
} 
@end