开发者

Dragging the view

开发者 https://www.devze.com 2023-03-31 07:46 出处:网络
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

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?


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.

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

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:

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

What I am suggesting is something like this:

lastDrag = [NSEvent mouseLocation];

other codes are just the same.

0

精彩评论

暂无评论...
验证码 换一张
取 消