2013-08-27 17 views
5

Lubię podklasę NSProgressIndicator. Użyłem tego kodu i ustawić podklasy w Builder interfejs:Podklasa 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); 

Kiedy aplikacja uruchamia jego wygląd tak: App start

Jednak podczas kopiowania postęp stary pasek pokazuje się. During copying

Co jest nie tak?

+0

zapomniałeś dodać [SUPER drawRect: rect] –

+0

To jest nie działa z [SUPER drawRect: rect]. – Konobi

+0

Dodaje więc NSLog do mojej podklasy i wywołania podklasy tylko raz na początku, ale podczas postępu kopiowania klasa nigdy nie jest wywoływana. – Konobi

Odpowiedz

2

Wygląda na to, że postęp paska postępu nie został narysowany w drawRect:, więc samo przesłanianie drawRect: nie wystarczy. Jeśli jednak utworzysz kopię paska postępu, odpowiadasz za wykonanie całego rysunku.

Z documentation:

Klasa widok automatycznie tworzy warstwę podkładową dla ciebie (używając makeBackingLayer jeśli nadpisane) i trzeba użyć mechanizmy rysowania klasy widoku za.

sprawdzić „Warstwa Core Animation” w IB lub dodać do swojej klasy sub:

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

Tak, zapomniałem ustawić Core Animation Layer. Thx ... nowość w Cocoa nigdy nie próbowałem podklasy przed; D – Konobi

1

Śledziłem powyższej rady (! Dzięki), ale niestety odkryliśmy, że kiedy NSProgressIndicator był zmieniany, zniknął, ale tylko przy pierwszym obejrzeniu (był w szufladzie).

Zamiast próbować zrozumieć, co się dzieje, zdałem sobie sprawę, że faktycznie nie potrzebujesz starej kontroli, ponieważ to co robiłem jest bardzo proste (wskaźnik siły, który zmienia kolor). Po prostu utwórz podklasę NSView.

Więc to jest to:

@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