拖动视图

13

我有一个NSView,我将其添加为另一个NSView的子视图。我想要能够拖动第一个NSView在父视图中移动。我有一些部分工作的代码,但是NSView沿Y轴的移动方向与我的鼠标拖动相反。(例如,我向下拖动,它向上移动,反之亦然)。

这是我的代码:

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

视图是翻转的,尽管我已将其更改回默认设置,但似乎没有任何区别。我做错了什么?

2个回答

16
这个问题的最佳解决方法是首先对坐标空间有充分的理解。
首先,重要的是要理解当我们谈论窗口的“框架”时,它是在父视图的坐标系中。这意味着调整视图本身的翻转不会真正产生影响,因为我们没有改变视图本身内部的任何内容。
但你的直觉是正确的,翻转在这里很重要。
默认情况下,你的代码似乎会运行;也许你的父视图已经被翻转了(或者没有被翻转),并且处于一个与你预期不同的坐标空间中。
与其随机地翻转和取消翻转视图,不如将所处理的点转换为已知的坐标空间。
我已经编辑了你上面的代码,始终将其转换为父视图的坐标空间,因为我们正在处理框架原点。如果可拖动视图放置在翻转或非翻转的父视图中,这将起作用。
// -------------------- 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;
}
此外,我建议您重构代码,只需处理原始的鼠标按下位置和指针当前位置,而不是处理鼠标拖动事件之间的增量。这可能会导致未预期的结果。
相反,只需存储拖动视图的原点和鼠标指针之间的偏移量(其中鼠标指针在视图内),并将帧原点设置为鼠标指针的位置减去偏移量。
以下是一些额外的阅读材料: Cocoa绘图指南 Cocoa事件处理指南

0

我认为你应该根据鼠标的位置进行计算,因为根据我的测试,这样会更加平滑。因为下面这种方式只提供应用程序窗口坐标系内的位置:

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

我建议的是这样的内容:
lastDrag = [NSEvent mouseLocation];

其他代码都是一样的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接