2013-03-18 1 views
1

Я создал подкласс a NSView для создания пользовательского интерфейса, включая NSTextView. Поэтому я использую метод drawRect для рисования моего пользовательского интерфейса. Я также создал подкласс NSImageView, чтобы получить событие mousedown. Всякий раз, когда я нажимаю на свой подкласс NSImageView, метод drawRect моего представления вызывается в бесконечном цикле, и я не могу понять, почему. Создание пользовательских пользовательских интерфейсов является новым для меня, поэтому, возможно, я делаю что-то по существу не так?NSView Subclass drawRect вызывается в бесконечном цикле

TWIComposeFrameView.m:

#import "TWIComposeWindowFrameView.h" 
#import "TWIImageView.h" 

@implementation TWIComposeWindowFrameView 

#pragma mark draw Rect of the View 

// 
// drawRect: 
// 
// Draws the frame of the window. 
// 
- (void)drawRect:(NSRect)rect 
{ 
    //// Color Declarations 
    NSColor* mainClrWhite = [NSColor colorWithCalibratedRed: 0.954 green: 0.954 blue:  0.954 alpha: 1]; 
    NSColor* transpGrey = [NSColor colorWithCalibratedRed: 0.224 green: 0.224 blue: 0.224 alpha: 0.745]; 
    NSColor* composeClrGrey = [NSColor colorWithCalibratedRed: 0.858 green: 0.842 blue: 0.842 alpha: 1]; 

    //// Abstracted Attributes 
    NSRect composeRectRect = NSMakeRect(20, 70, 475, 210); 
    NSRect attachmentRectRect = NSMakeRect(499, 195, 85, 85); 


    //// transpRect Drawing 
    NSBezierPath* transpRectPath = [NSBezierPath bezierPathWithRoundedRect: NSMakeRect(1, 0, 599, 299) xRadius: 10 yRadius: 10]; 
    [transpGrey setFill]; 
    [transpRectPath fill]; 


    //// mainRect Drawing 
    NSBezierPath* mainRectPath = [NSBezierPath bezierPathWithRoundedRect: NSMakeRect(10, 10, 580, 280) xRadius: 10 yRadius: 10]; 
    [mainClrWhite setFill]; 
    [mainRectPath fill]; 


    //// composeRect Drawing 
    NSBezierPath* composeRectPath = [NSBezierPath bezierPathWithRoundedRect: composeRectRect xRadius: 10 yRadius: 10]; 
    [composeClrGrey setFill]; 
    [composeRectPath fill]; 


    //// attachmentRect Drawing 
    NSBezierPath* attachmentRectPath = [NSBezierPath bezierPathWithRoundedRect: attachmentRectRect xRadius: 10 yRadius: 10]; 
    [mainClrWhite setFill]; 
    [attachmentRectPath fill]; 
    [composeClrGrey setStroke]; 
    [attachmentRectPath setLineWidth: 1]; 
    [attachmentRectPath stroke]; 
} 

- (id)initWithFrame:(NSRect)rect 
{ 
    if (![super initWithFrame:rect]) 
     return nil; 

    NSColor* composeClrGrey = [NSColor colorWithCalibratedRed: 0.858 green: 0.842 blue: 0.842 alpha: 1]; 
    NSRect composeRectRect = NSMakeRect(20, 70, 475, 210); 
    NSRect attachmentRectRect = NSMakeRect(499, 195, 85, 85); 
    //// Add Controls 
    [self addComposeTextView:composeClrGrey composeRectRect:composeRectRect]; 
    [self addAttachmentImageView:attachmentRectRect]; 
    return self; 
} 

#pragma mark - 
#pragma mark Add Controls to View 

// 
// Create and Add the Compose TextView 
// 
- (void)addComposeTextView:(NSColor *)composeClrGrey composeRectRect:(NSRect)composeRectRect 
{ 
    NSTextView *composeTextView; 
    if (composeTextView == nil) 
    { 
     composeTextView = [[NSTextView alloc] initWithFrame:composeRectRect]; 
     [composeTextView setBackgroundColor:composeClrGrey]; 
     [composeTextView setFont:[NSFont fontWithName:@"Helvetica" size:18]]; 
     [composeTextView setRichText:NO]; 
     [self addSubview:composeTextView]; 
    } 
} 

// 
// Create and Add the Attachemant ImageView 
// 
- (void)addAttachmentImageView:(NSRect)attachmentRectRect 
{ 
    NSImage *defaultImage = [NSImage imageNamed:@"168-upload-photo-2"]; 
    NSRect ivRect = NSMakeRect(attachmentRectRect.origin.x + 5, attachmentRectRect.origin.y + 5, attachmentRectRect.size.width - 10, attachmentRectRect.size.height - 10); 
    TWIImageView *imageView = [[TWIImageView alloc] initWithFrame:ivRect]; 
    imageView.delegate = self; 
    [imageView setEditable:YES]; 
    [self addSubview:imageView]; 
    [imageView setImage:defaultImage]; 
} 

#pragma mark - 
#pragma mark TWIImageView Delegate 

// 
// mouseDown Event on TWIImageView 
// 
- (void)myImageView:(TWIImageView *)view mouseDown:(NSEvent *)event 
{ 
    NSLog(@"imageView clicked"); 
} 
#pragma mark - 

@end 

TWIImageView.h

@class TWIImageView; 
@protocol TWIImageViewDelegate <NSObject> 

- (void)myImageView:(TWIImageView *)view mouseDown:(NSEvent *)event; 

@end 

@interface TWIImageView : NSImageView 
{ 

} 

@property (assign) id<TWIImageViewDelegate> delegate; 

@end 

TWIImageView.m:

#import "TWIImageView.h" 

@implementation TWIImageView 

@synthesize delegate = _delegate; 

- (void)mouseDown:(NSEvent *)event { 
    if([self.delegate respondsToSelector:@selector(myImageView:mouseDown:)]) { 
     [self.delegate myImageView:self mouseDown:event]; 
    } 
} 

@end 

Это неправильно, чтобы создать элементы управления в перезаписанной методе initWithFrame? Или моя TWIImageView хватает чего-то важного

StackTrace:

Thread 1, Queue : com.apple.main-thread 
#0 0x0000000100001cd0 in -[TWIComposeWindowFrameView drawRect:] at  /Users/thomaswickl/Documents/Development/Git  Projects/QuickQuick/QuickQuick/TWIComposeWindowFrameView.m:24 
#1 0x00007fff92efa170 in -[NSView _drawRect:clip:]() 
#2 0x00007fff92ef6fe3 in -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView: ]() 
#3 0x00007fff92ef7a74 in -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]() 
#4 0x00007fff93045fdb in -[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]() 
#5 0x00007fff92ef1d9d in -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]() 
#6 0x00007fff92ebbcc3 in -[NSView displayIfNeeded]() 
#7 0x00007fff93045e94 in -[NSNextStepFrame displayIfNeeded]() 
#8 0x00007fff92ebb1fc in _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints() 
#9 0x00007fff934868f1 in __83-[NSWindow _postWindowNeedsDisplayOrLayoutOrUpdateConstraintsUnlessPostingDisabled]_block_invoke_01208() 
#10 0x00007fff92b39417 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__() 
#11 0x00007fff92b39381 in __CFRunLoopDoObservers() 
#12 0x00007fff92b147b8 in __CFRunLoopRun() 
#13 0x00007fff92b140e2 in CFRunLoopRunSpecific() 
#14 0x00007fff90ce8eb4 in RunCurrentEventLoopInMode() 
#15 0x00007fff90ce8b94 in ReceiveNextEventCommon() 
#16 0x00007fff90ce8ae3 in BlockUntilNextEventMatchingListInMode() 
#17 0x00007fff92eb8563 in _DPSNextEvent() 
#18 0x00007fff92eb7e22 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]() 
#19 0x00007fff92eaf1d3 in -[NSApplication run]() 
#20 0x00007fff92e53c06 in NSApplicationMain() 
#21 0x0000000100001242 in main at /Users/thomaswickl/Documents/Development/Git Projects/QuickQuick/QuickQuick/main.m:13 
#22 0x00007fff955db7e1 in start() 
+0

Честно говоря, я не вижу петлю. Если есть один, вы не можете просто установить точку прерывания в начале drawRect: и продолжить пару раз, а затем посмотреть на стек вызовов, какой из вызванных методов на самом деле вызывает drawRect снова и снова? –

+1

Возможно, вам стоит рассмотреть возможность сохранения и восстановления графического контекста во время '-drawRect:'. Я не знаю, что это решит вашу проблему с циклом, но это, вероятно, решит некоторые проблемы в будущем. – gaige

+0

Я не вижу проблемы с циклом в этом коде. Я думаю, что это происходит где-то в другом месте ... просто посмотрите, всегда ли вы вызываете setNeedDisplay (в цикле) !!! –

ответ

0

Сохранение и восстановление графического контекста в методе drawRect решена Проблема.

1

Я не думаю, что этот ответ будет устранить проблему. Однако метод init может возвращать другой объект, чем self. Поэтому вам лучше использовать это:

if (!(self = [super initWithFrame:rect])) 
    return nil; 
+0

Спасибо, я изменил свою реализацию. – CaptnCrash

0

Добавить

[супер DrawRect: Rect];

в методе DrawRect

 Смежные вопросы

  • Нет связанных вопросов^_^