拖动视图
我有一个 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;
}
视图被翻转,尽管我将其改回默认值,但似乎没有什么区别。我做错了什么?
I have an NSView
which I am adding as a sub-view of another NSView
. I want to be able to drag the first NSView
around the parent view. I have some code that is partially working but there's an issue with the NSView
moving in the opposite direction on the Y axis from my mouse drag. (i.e. I drag down, it goes up and the inverse of that).
Here's my code:
// -------------------- 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;
}
The view is flipped, though I changed that back to the default and it didn't seem to make a difference. What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
解决这个问题的最佳方法是从对坐标空间的深入理解开始。
首先,重要的是要理解,当我们谈论窗口的“框架”时,它位于超级视图的坐标空间中。这意味着调整视图本身的翻转度实际上不会产生影响,因为我们没有更改视图本身内部的任何内容。
但你认为翻转在这里很重要的直觉是正确的。
默认情况下,您输入的代码似乎可以工作;也许您的超级视图已翻转(或未翻转),并且它位于与您预期不同的坐标空间中。
最好将您正在处理的点转换为已知的坐标空间,而不是只是随机翻转和展开视图。
我已经编辑了上面的代码以始终转换为超级视图的坐标空间,因为我们正在使用框架原点。如果您的可拖动视图放置在翻转或非翻转的超级视图中,这将起作用。
此外,我建议重构您的代码以简单地处理原始鼠标按下位置和指针的当前位置,而不是处理 mouseDragged 事件之间的增量。这可能会导致意想不到的结果。
相反,只需存储拖动视图的原点和鼠标指针(鼠标指针位于视图内)之间的偏移量,并将框架原点设置为鼠标指针的位置减去偏移量。
这里有一些额外的阅读内容:
Cocoa 绘图指南
Cocoa 事件处理指南
The best way to approach this problem is by starting with a solid understanding of coordinate spaces.
First, it is critical to understand that when we talk about the "frame" of a window, it is in the coordinate space of the superview. This means that adjusting the flippedness of the view itself won't actually make a difference, because we haven't been changing anything inside the view itself.
But your intuition that the flippedness is important here is correct.
By default your code, as typed, seems like it would work; perhaps your superview has been flipped (or not flipped), and it is in a different coordinate space than you expect.
Rather than just flipping and unflipping views at random, it is best to convert the points you're dealing with into a known coordinate space.
I've edited your above code to always convert into the superview's coordinate space, because we're working with the frame origin. This will work if your draggable view is placed in a flipped, or non-flipped superview.
Additionally, I'd recommend refactoring your code to simply deal with the original mouse-down location, and the current location of the pointer, rather than deal with the deltas between mouseDragged events. This could lead to unexpected results down the line.
Instead simply store the offset between the origin of dragged view and the mouse pointer (where the mouse pointer is within the view), and set the frame origin to the location of the mouse pointer, minus the offset.
Here is some additional reading:
Cocoa Drawing Guide
Cocoa Event Handling Guide
我认为你应该根据鼠标的位置来计算,因为根据我的测试,它会变得更平滑。因为像下面这样的方式只提供应用程序窗口坐标系内的位置:
我的建议是这样的:
其他代码都是一样的。
I think you should calculate according to the position of mouse, cause according to my test,it gets more smooth.Because The way like below only provide the position inside the application's window coordinate system:
What I am suggesting is something like this:
other codes are just the same.