2011-08-25 4 views
9

다른 NSView의 하위보기로 추가 할 NSView가 있습니다. 상위 뷰를 중심으로 첫 번째 NSView를 드래그 할 수 있기를 원합니다. 부분적으로 작동하는 일부 코드가 있지만 NSView가 내 마우스 끌기에서 Y 축의 반대 방향으로 이동하는 문제가 있습니다. (즉, 아래로 드래그하면 위로 올라가고 그 반대가됩니다). 내가 그 다시 기본값으로 변경하고 변화를 보이지 않았지만,NSView :보기 드래그

// -------------------- MOUSE EVENTS ------------------- \\ 

- (BOOL) acceptsFirstMouse:(NSEvent *)e { 
return YES; 
} 

- (void)mouseDown:(NSEvent *) e { 

//get the mouse point 
lastDragLocation = [e locationInWindow]; 

} 

- (void)mouseDragged:(NSEvent *)theEvent { 

NSPoint newDragLocation = [theEvent locationInWindow]; 
NSPoint thisOrigin = [self frame].origin; 
thisOrigin.x += (-lastDragLocation.x + newDragLocation.x); 
thisOrigin.y += (-lastDragLocation.y + newDragLocation.y); 
[self setFrameOrigin:thisOrigin]; 
lastDragLocation = newDragLocation; 
} 

보기가 뒤집어 :

여기 내 코드입니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

답변

13

이 문제에 접근하는 가장 좋은 방법은 좌표 공간에 대한 확실한 이해로 시작하는 것입니다.

우선, 창의 "프레임"에 대해 이야기 할 때, 그것은 수퍼 뷰의 좌표 공간에 있음을 이해하는 것이 중요합니다. 즉, 뷰 내부에서 아무 것도 변경하지 않았기 때문에 뷰 자체의 반전을 조정해도 실제로 차이가 발생하지 않습니다.

하지만 여기에 반전이 중요하다는 직감이 맞습니다.

기본적으로 코드는 입력 된대로 작동하는 것처럼 보입니다. 아마도 수퍼 뷰가 뒤집어 졌거나 뒤집혀지지 않았을 것이며, 기대 한 것보다 다른 좌표 공간에있을 것입니다.

임의로보기를 뒤집거나 펼치기보다는 다루는 지점을 알려진 좌표 공간으로 변환하는 것이 가장 좋습니다.

우리는 프레임 원점을 다루기 때문에 항상 위의 코드를 편집하여 superview의 좌표 공간으로 변환했습니다. 드래그 할 수있는 뷰가 뒤집힌 또는 수퍼 뷰가 아닌 슈퍼 뷰에 배치 된 경우이 작업이 가능합니다.

// -------------------- MOUSE EVENTS ------------------- \\ 

- (BOOL) acceptsFirstMouse:(NSEvent *)e { 
    return YES; 
} 

- (void)mouseDown:(NSEvent *) e { 

    // Convert to superview's coordinate space 
    self.lastDragLocation = [[self superview] convertPoint:[e locationInWindow] fromView:nil]; 

} 

- (void)mouseDragged:(NSEvent *)theEvent { 

    // We're working only in the superview's coordinate space, so we always convert. 
    NSPoint newDragLocation = [[self superview] convertPoint:[theEvent locationInWindow] fromView:nil]; 
    NSPoint thisOrigin = [self frame].origin; 
    thisOrigin.x += (-self.lastDragLocation.x + newDragLocation.x); 
    thisOrigin.y += (-self.lastDragLocation.y + newDragLocation.y); 
    [self setFrameOrigin:thisOrigin]; 
    self.lastDragLocation = newDragLocation; 
} 

또한, 단순히의 mouseDragged 이벤트 사이의 델타 원래 마우스 다운 위치, 포인터의 현재 위치가 아닌 거래를 처리하는 코드를 리팩토링하는 것이 좋습니다 것입니다. 이로 인해 예기치 않은 결과가 발생할 수 있습니다.

드래그 한 뷰의 원점과 마우스 포인터 (뷰 내에있는 마우스 포인터) 사이에 오프셋을 저장하고 프레임 원점에서 오프셋을 뺀 마우스 포인터의 위치를 ​​설정하면됩니다. 여기

이 몇 가지 추가 읽고 : 난 당신이 내 테스트에 따라, 마우스의 위치에 따라 계산 일으킬해야한다고 생각

Cocoa Drawing Guide

Cocoa Event Handling Guide

0

, 그것은 더 smooth.Because 방법을 얻는다 아래처럼 응용 프로그램의 창 좌표계 안의 위치 만 제공하십시오 :

[[self superview] convertPoint:[theEvent locationInWindow] fromView:nil]; 

모자 나는이 같은 것을 제안합니다 :

lastDrag = [NSEvent mouseLocation]; 

다른 코드는 동일합니다.