【发布时间】:2012-01-13 15:10:23
【问题描述】:
我正在 NSView 的自定义子类上绘制一个矩形,然后可以在视图的边界内拖动它:
执行此操作的代码是:
// Get the starting location of the mouse down event.
NSPoint location = [self convertPoint: [event locationInWindow] fromView: nil];
// Break out if this is not within the bounds of the rect.
if (!NSPointInRect(location, [self boundsOfAllControlPoints])) {
return;
}
while (YES) {
// Begin modal mouse tracking, looking for mouse dragged and mouse up events
NSEvent *trackingEvent = [[self window] nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask)];
// Get tracking location and convert it to point in the view.
NSPoint trackingLocation = [self convertPoint:[trackingEvent locationInWindow] fromView:nil];
// Calculate the delta's of x and y compared to the previous point.
long dX = location.x - trackingLocation.x;
long dY = location.y - trackingLocation.y;
// Update all points in the rect
for (int i = 0; i < 4; i++) {
NSPoint newPoint = NSMakePoint(points[i].x - dX, points[i].y - dY);
points[i] = newPoint;
}
NSLog(@"Tracking location x: %f y: %f", trackingLocation.x, trackingLocation.y);
// Set current location as previous location.
location = trackingLocation;
// Ask for a redraw.
[self setNeedsDisplay:YES];
// Stop mouse tracking if a mouse up is received.
if ([trackingEvent type] == NSLeftMouseUp) {
break;
}
}
我基本上捕捉到鼠标按下事件并检查它的位置是否在可拖动的矩形内。如果是,我开始在 trackingEvent 中跟踪鼠标的移动。我计算 x 和 y 坐标的增量,为可拖动的矩形创建新点,并请求刷新视图显示。
虽然它有效,但它看起来有点“业余”,因为在拖动过程中,鼠标指针会赶上被拖动的形状并最终越过它的边界。在其他拖动操作中,从拖动操作的开始到结束,您会看到鼠标指针固定在被拖动对象的位置。
造成这种影响的原因是什么?
编辑:
我已经按照 Rob 的回答改变了我的方法,并采用了三种方法:
- (void) mouseDown: (NSEvent*) event {
// There was a mouse down event which might be in the thumbnail rect.
[self setDragStartPoint: [self convertPoint: [event locationInWindow] fromView: nil]];
// Indicate we have a valid start of a drag.
if (NSPointInRect([self dragStartPoint], [self boundsOfAllControlPoints])) {
[self setValidDrag: YES];
}
}
- (void) mouseDragged: (NSEvent *) anEvent {
// Return if a valid drag was not detected during a mouse down event.
if (![self validDrag]) {
return;
}
NSLog(@"Tracking a drag.");
// Get tracking location and convert it to point in the view.
NSPoint trackingLocation = [self convertPoint: [anEvent locationInWindow] fromView: nil];
// Calculate the delta's of x and y compared to the previous point.
long dX = [self dragStartPoint].x - trackingLocation.x;
long dY = [self dragStartPoint].y - trackingLocation.y;
// Update all points in the rect
for (int i = 0; i < 4; i++) {
NSPoint newPoint = NSMakePoint(points[i].x - dX, points[i].y - dY);
points[i] = newPoint;
}
// Ask for a redraw.
[self setNeedsDisplay:YES];
NSLog(@"Tracking location x: %f y: %f", trackingLocation.x, trackingLocation.y);
// Set current location as previous location.
[self setDragStartPoint: trackingLocation];
NSLog(@"Completed mouseDragged method. Allow for repaint.");
}
- (void) mouseUp: (NSEvent *) anEvent {
// End the drag.
[self setValidDrag: NO];
[self setNeedsDisplay: YES];
}
虽然效果稍微好一些,但由于矩形最终拖到鼠标指针的移动方向后面,仍然存在明显的延迟。当我在拖动过程中缓慢移动鼠标时,这一点尤其明显。
编辑 2:
知道了。问题在于计算增量。我用了 long ,而我应该使用 float。现在效果很好。
【问题讨论】:
-
感谢分享实现鼠标拖动的代码。
标签: cocoa drag-and-drop