2014-11-27 1 views
2

일부 NSView의 일부를 다시 그려야합니다. 뷰의 전체 영역까지 - NSView setNeedDisplay : rect가 필요한 것보다 큰 영역을 다시 그려야합니다.

- (IBAction)onUpdateView:(id)sender 
{ 
    NSRect updatedRect = ... // Redraw updated area only. 
    [self.view setNeedsDisplayInRect:updatedRect]; 
} 

나는이 간단하고 확실한 솔루션을 사용

는 석영 디버그 훨씬 더 큰 영역의 다시 그리기를 강조한다. 문제가 사라 :

나는 [NSView의 setNeedsDisplayInRect]의 호출이 다음 실행 루프 사이클로 연기, 또는 경우 단순히 [0 runloop의 runUntilDate을] : 할 것으로 나타났습니다

- (IBAction)onUpdate:(id)sender 
{ 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     [self setNeedsDisplayInRect:updatedRect]; 
    }); 
} 

또는

-(void)mouseUp:(NSEvent*)event 
{ 
    NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil]; 

    int size = 100; 
    [self setNeedsDisplayInRect:NSMakeRect(p.x-size/2, p.y-size/2, size, size)]; 
} 
:
- (IBAction)onUpdateAndRunLoop:(id)sender 
{ 
    [self.view setNeedsDisplayInRect:updatedRect]; 
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.0]]; // EEW 
} 

하지만 setNeedsDisplayInRect 경우 이 이는 mouseDown 핸들러에서 호출되어, 모든이 해커없이 작동

무슨 일이 일어나고 어떻게해야합니까? 이 문제에 대한

고립 된 Xcode 프로젝트는 여기에 있습니다 : http://beta.kalinsky.ru/wtf/testRedraw.tar.gz

+0

다시 그리려는보기에는 사용자 지정 drawRect 메서드가 있습니까? 그렇다면 거기에 모든 것을 그려 넣거나 dirtyRect를 존중합니까? 그 rect에있는 것들만 다시 그립니다. 아니면 그보기가 잘리고 그 화면 밖의 내용도 그려지 는가? – HAS

+0

@HAS : 물론, 내 첫 번째 의심이었습니다. 첨부 된 프로젝트의 drawRect 메소드는 문자 그대로 "[NSBezierPath fillRect : dirtyRect];"입니다. –

+0

답변과 의견에서 아래에 제공된 것보다 더 나은 설명을 찾았습니까? 그리는 경우 텍스트와 투명도가 성능에 중요한 영향을줍니다. –

답변

2

이 바람직하지 않은 동작입니다 당신이 그렇게 확실하게 무엇? Quartz Debugger에서 볼 수있는 동작은 Update 버튼을 클릭하면 클릭 된 버튼의 사각형과 전달 된 dirtyRect의 교차점이 깜박이라는 것을 보여줍니다. 이는 시스템이 효율적으로 실행 루프 (마우스를 올렸을 때)와 동일한 패스 내에서 필요한 모든 도면을 병합 할 때 예상됩니다.

다른 해킹 방법은 버튼의 상태가 하나 (실제로는 마우스를 아래로 내리고 마우스를 위로)로 처리하고보기의 업데이트가 다음 단계에서 처리되기 때문에이 동작을 우회합니다. 이는 지연된 드로잉 클릭에서 업데이트에 대한 세심한주의를 기울이면 확인됩니다 (버튼이 아래쪽으로 깜박이고 다시 위로 올라가면 뷰의 더티 영역이 깜박입니다). 뷰 자체의 클릭에는 아무 것도 (잘, 기술적으로는 불투명 한 조상) 관계가 없으므로 모든 뷰의 더러운 직사각형의 결합이 요청 된 rect에 한정됩니다.

이 정보가 도움이되기를 바랍니다.

+0

합리적인 것 같지만이 동작이 바람직하고 정확하다는 확신이 들지 않습니다. 나는 또 다른 실험을 시도했다. 나는 메인 윈도우의 한 구석에 텍스트 라벨을 붙이고 반대편에 그 재미있는 사각형을 그리기 시작했다. 이 경우 QuartzDebug가 전체 2560x1600 영역을 깜박이고 WindowServer는 ~ 50 % CPU를 사용합니다. http://beta.kalinsky.ru/wtf/deferred_vs_direct.png (플롯은 WindowServer 프로세스의 CPU 사용량을 보여줍니다) –

+1

이상하게 보입니다. . 사용자 정의보기의 -isOpaque를 재정 의하여 YES를 반환하면 어떻게됩니까? –

+0

와우, 첨부 된 xcodeproj의 문제가 완전히 수정되었습니다. :-) http://beta.kalinsky.ru/wtf/opaque_vs_transparent.png, 출처 : http://beta.kalinsky.ru/wtf/testRedraw-opaque.tar .gz 하지만 시스템이 왜 밑으로보기가 없는데도 전체 영역을 다시 칠하기로 결정한 이유는 분명하지 않습니다. –

관련 문제