2014-11-27 1 views
0

자신의 클래스에 @property이있는 3 개의 이미지가있는보기가 있습니다. 이 이미지 중 하나를 마우스 오른쪽 버튼으로 클릭하면 NSMenuItems 인 하위 메뉴가있는 NSMenu이 표시됩니다. 모든 항목은 각각 tag- (IBAction)selectImage:(id)sender이라는 IBAction으로 전송됩니다. 물론 senderNSMenuItem입니다. 사용자가 어떤 이미지를 클릭했는지 어떻게 알 수 있습니까? 그래서 나는 기본적으로 sender의 부모에게 발신자를 찾고 있습니다.NSMenuItem의 초 기자 받기

아니면 내 메뉴를 잘못 작성하고 있습니까?

답변

0

위에 여전히 커서를 확인합니다. 메뉴 항목에 명시적인 타겟을 설정하는 대신 First Responder (또는 코드에서 코드를 수행하는 경우 nil)을 사용하십시오.

기본적으로 첫 번째 응답자는 상황에 맞는 메뉴를 소유 한보기입니다 ("상황에 맞는 메뉴의 경우 관련보기부터 시작하여 상황에 맞는 메뉴가 표시된 창의 응답자 체인으로 검색이 제한됩니다) "documentation에 따라).

따라서 사용자가 NSImageView의 하위 클래스를 만들고 거기에 필요한 동작을 구현하면 기본적으로 해당 메시지가 수신됩니다. 그들은 당신의 컨트롤러 객체에 대한 간단한 리디렉션 될 수 있지만,이 방법에 클릭 된 뷰 알 (이이 경우에 self을 때문에!)


이 응답이 이전 응답의 편집, 인 훨씬 적은 우아한 : NSMenu의 서브 클래스를 생성하여

시작 이미지보기에 약한 참조를 저장하는 추가 속성이 그 (의이 PPMenu를 부르 자) (의이 imageView를 부르 자). 해당 클래스를 XIB에서 메뉴의 클래스로 설정하고 메뉴를 이미지보기의 상황에 맞는 메뉴로 설정합니다 (또는 XIB에없는 경우 콘센트 만 추가).당신이 -menuForEvent:NSImageView 서브 클래스에서 오버라이드 (override)하는 경우

이제, 당신은 사용 그렇지 않은 경우는 IB에서 설정되어있는 경우합니다 (PPMenu 인스턴스를 검색 할 수 있습니다 super를 호출하여 시작 ... 상황에 맞는 메뉴를 사용자 정의 할 수있을거야 콘센트)를 열고 self에 추가 한 imageView 속성을 설정합니다 (사용자가 이미지보기 코드에 있으므로).

이제 액션 코드에서 ((PPMenu*)(sender.menu)).imageView을 사용하여 메뉴와 연결된 이미지보기를 검색 할 수 있습니다.

1

뷰 클래스에서 -menuForEvent:을 덮어 쓰고 이벤트에 대한 참조를 저장하거나 위치를 기억하거나 어떤 이미지가 맞았는지 확인하고 기억합니다. 그런 다음 작업 메서드에서 기억 된 이벤트/위치/이미지 인덱스를 사용하여 응답하는 방법을 결정합니다. 물론

는, 뷰의 좌표에서 이벤트 위치를 얻기 위해 당신이 할 것 : 그 시점 뷰의 특정 부분에있는 경우

NSPoint point = [self convertPoint:event.locationInWindow fromView:nil]; 

테스트 할 때 사용한다 :

if ([self mouse:point inRect:rectOfInterest]) 
    // ... 
0

오른쪽 클릭 이벤트 핸들러에서 클릭 한 이미지를 기억하십시오.

#pragma mark - mouse events 

- (void)rightMouseDown:(NSEvent *)event 
{ 
    [super rightMouseDown:event]; // if you don't want to push events to parent view - remove this line 
    NSPoint eventLocation = [event locationInWindow]; // get mouse location in window coordinates 
    NSPoint localLocation = [self convertPoint:eventLocation fromView:nil]; // get mouse location in view coordinates 
    selectedImageView = nil; // set it nil each time right mouse down 
    NSArray *images = @[imageView0, imageView1, imageView2]; // all your image view outlets, check if they aren't nil 
    for (NSImageView *imageView in images) 
    if (NSPointInRect(localLocation, imageView.frame)) 
    { 
     selectedImageView = imageView; // selectedImageView should be a class member 
     break; 
    } 
} 

#pragma mark - menu actions 

- (IBAction)selectImage:(id)sender 
{ 
    if (selectedImageView) 
    { 
    // your code here 
    } 
} 

이것은 수행해야하는 작업을 요약 한 것입니다. 그러나 사용자가 image0 근처에서 마우스 오른쪽 버튼을 누른 다음 커서를 이미지에서 드래그하여 마우스를 놓으십시오. 이 다른 마우스 이벤트 핸들러 rightMouseUp를 오버라이드 (override) 할 필요가 그냥 당신은 문제가 길을 잘못 접근하고있는 selectedImageView

#pragma mark - mouse events 

//... 

- (void)rightMouseUp:(NSEvent *)event 
{ 
    [super rightMouseUp:event]; 
    if (!selectedImageView) 
    return; // nothing to check here 
    NSPoint eventLocation = [event locationInWindow]; 
    NSPoint localLocation = [self convertPoint:eventLocation fromView:nil]; 
    if (!NSPointInRect(localLocation, selectedImageView.frame)) // the mouse not above the selectedImageView 
    selectedImageView = nil; 
    else 
    { 
     // there may be NSMenu instance initializing 
    } 
} 
+0

'-rightMouseDown :'을 사용하는 것으로 충분하지 않습니다. Contextual 메뉴는 Ctrl 키를 누른 채 클릭하여 시작할 수도 있습니다.이 방법은 해당 메소드를 통과하지 않습니다. 접근성과 같은 추가 방법이있을 수 있습니다. 또한 상황에 맞는 메뉴가 마우스를 아래로 나타납니다. 마우스를 올리기 전에 커서를 움직여도 상관 없습니다. 실제로는 정상입니다. 나는 마우스가 메뉴 트래킹에 의해 캡쳐된다고 생각하기 때문에 뷰가 그것을받을 것이라고 생각하지 않는다. 그래도 그 마지막 비트는 확인하지 않았습니다. –

+0

@KenThomases 글쎄, 네가 맞아, 방금 imageView를 기억하고, 인스턴스화하는 과정을 전혀 언급하지 않았다. – Astoria

+0

흠? 나는 당신이 메뉴를 인스턴스화 할 필요가 있다고 제안하는 것을 의미하지는 않았다. 내 포인트는'-rightMouseDown :'은 사용자가 문맥 메뉴를 원할 때 전혀 호출되지 않을 수도 있다는 것이다. 마우스 오른쪽 버튼을 클릭 할 필요가 없기 때문입니다. 또한 OP는 이미지 ** 뷰 **를 언급하지 않았습니다. 사실, 하나의보기에 단지 이미지 만있는 것이 좋습니다. –

관련 문제