2013-08-27 47 views
5

tôi thích phân lớp NSProgressIndicator. Tôi đã sử dụng đoạn mã này và tôi đặt Subclass trong Interface Builder:Phân lớp 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); 

Khi ứng dụng bắt đầu trông nó như thế này: App start

Nhưng trong bản sao tiến bộ thanh cũ xuất hiện. During copying

Có vấn đề gì?

+0

Bạn quên để thêm [siêu drawRect: rect] –

+0

Nó không làm việc với [siêu drawRect: rect]. – Konobi

+0

Vì vậy, tôi thêm NSLog vào phân lớp của tôi và các lớp con chỉ gọi một lần khi bắt đầu nhưng trong quá trình sao chép lớp không bao giờ được gọi. – Konobi

Trả lời

2

Dường như tiến độ của thanh tiến trình không được vẽ trong drawRect:, vì vậy chỉ ghi đè drawRect: là không đủ. Tuy nhiên, nếu bạn thực hiện lớp thanh tiến trình được sao lưu, bạn có trách nhiệm thực hiện tất cả bản vẽ.

Từ documentation:

Lớp xem tự động tạo ra một lớp ủng hộ cho bạn (sử dụng makeBackingLayer nếu ghi đè), và bạn phải sử dụng cơ chế vẽ lớp quan điểm của.

Kiểm tra "Core Animation Layer" trong IB hoặc thêm này đến lớp phụ của bạn:

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

Vâng tôi quên đặt Core Animation Layer. Thx ... sry mới để ca cao tôi không bao giờ cố gắng để phân lớp trước; D – Konobi

1

Tôi làm theo các lời khuyên ở trên (! Thanks), nhưng tiếc là phát hiện ra rằng khi NSProgressIndicator được thay đổi kích cỡ, nó biến mất, nhưng chỉ trên lần xem đầu tiên (nó nằm trong ngăn kéo). Thay vì cố gắng và hiểu những gì đang xảy ra, tôi nhận ra bạn không thực sự cần sự kiểm soát cũ, như những gì tôi đã làm là rất đơn giản (một chỉ số sức mạnh thay đổi màu sắc). Chỉ cần tạo một lớp con của NSView.

Vì vậy, đây là nó:

@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