2011-08-25 31 views
9

Tôi có NSView mà tôi đang thêm làm chế độ xem phụ của một NSView khác. Tôi muốn có thể kéo NSView đầu tiên xung quanh chế độ xem gốc. Tôi có một số mã đó là một phần làm việc nhưng có một vấn đề với NSView di chuyển theo hướng ngược lại trên trục Y từ kéo chuột của tôi. (tức là tôi kéo xuống, nó đi lên và ngược lại).NSView: Kéo chế độ xem

Dưới đây là mã của tôi:

// -------------------- 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; 
} 

quan điểm là lộn, mặc dù tôi đã thay đổi lại cho rằng mặc định và nó dường như không tạo sự khác biệt. Tôi đang làm gì sai?

Trả lời

13

Cách tốt nhất để tiếp cận vấn đề này là bắt đầu với sự hiểu biết vững chắc về không gian tọa độ.

Trước tiên, điều quan trọng là phải hiểu rằng khi chúng ta nói về "khung" của một cửa sổ, nó nằm trong không gian tọa độ của superview. Điều này có nghĩa là việc điều chỉnh tính lộn xộn của chính chế độ xem sẽ không thực sự tạo ra sự khác biệt, bởi vì chúng tôi đã không thay đổi bất kỳ thứ gì bên trong khung nhìn.

Nhưng trực giác của bạn rằng sự lộn xộn là quan trọng ở đây là chính xác.

Theo mặc định, mã của bạn, như được nhập, có vẻ như nó sẽ hoạt động; có lẽ giám sát của bạn đã bị lật (hoặc không bị lật), và nó nằm trong một không gian tọa độ khác với bạn mong đợi.

Thay vì chỉ lật và bỏ lượt xem một cách ngẫu nhiên, tốt nhất là chuyển đổi các điểm bạn đang xử lý thành không gian tọa độ đã biết.

Tôi đã chỉnh sửa mã trên của bạn để luôn chuyển đổi thành không gian tọa độ của người giám sát, bởi vì chúng tôi đang làm việc với nguồn gốc khung hình. Điều này sẽ hoạt động nếu chế độ xem có thể kéo của bạn được đặt trong trình giám sát lật hoặc không lật.

// -------------------- 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; 
} 

Thêm vào đó, tôi khuyên bạn nên refactoring mã của bạn chỉ đơn giản là đối phó với vị trí ban đầu chuột xuống, và vị trí hiện tại của con trỏ, hơn là đối phó với các vùng đồng bằng giữa các sự kiện mouseDragged. Điều này có thể dẫn đến kết quả bất ngờ xuống dòng. Thay vào đó, chỉ cần lưu trữ độ lệch giữa nguồn gốc của chế độ xem được kéo và con trỏ chuột (nơi con trỏ chuột nằm trong chế độ xem) và đặt nguồn gốc khung thành vị trí của con trỏ chuột, trừ giá trị bù trừ.

Dưới đây là một số bài đọc thêm:

Cocoa Drawing Guide

Cocoa Event Handling Guide

0

Tôi nghĩ bạn nên tính toán theo vị trí của chuột, gây ra theo thử nghiệm của tôi, nó được nhiều smooth.Because Cách như dưới đây chỉ cung cấp vị trí bên trong hệ thống tọa độ cửa sổ của ứng dụng:

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

W mũ tôi đề xuất là một cái gì đó như thế này:

lastDrag = [NSEvent mouseLocation]; 

các mã khác chỉ giống nhau.

Các vấn đề liên quan