2011-08-25 21 views
9

Tengo un NSView que estoy agregando como una subvista de otro NSView. Quiero ser capaz de arrastrar el primer NSView alrededor de la vista principal. Tengo un código que está funcionando parcialmente pero hay un problema con el NSView que se mueve en la dirección opuesta en el eje Y desde el arrastre de mi mouse. (es decir, arrastro hacia abajo, sube y retrocede).NSView: Arrastrando la vista

Aquí está mi código:

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

la vista se da la vuelta, aunque he cambiado de que en el valor predeterminado y no se parecía a hacer la diferencia. ¿Qué estoy haciendo mal?

Respuesta

13

La mejor manera de abordar este problema es comenzando con una sólida comprensión de los espacios de coordenadas.

En primer lugar, es fundamental comprender que cuando hablamos sobre el "marco" de una ventana, está en el espacio de coordenadas de la supervista . Esto significa que ajustar la flippingness de la vista en sí no marcará la diferencia, porque no hemos cambiado nada dentro de la vista.

Pero su intuición de que la flippingness es importante aquí es correcta.

De forma predeterminada, su código, como se escribe, parece que funcionaría; quizás su supervista ha sido volteada (o no volteada), y está en un espacio de coordenadas diferente del esperado.

En lugar de simplemente voltear y desenrollar vistas al azar, lo mejor es convertir los puntos que está tratando en un espacio de coordenadas conocido.

He editado el código anterior para convertirlo siempre en el espacio de coordenadas de la supervista, porque estamos trabajando con el origen del marco. Esto funcionará si su vista que se puede arrastrar se coloca en una supervista volteada o no volteada.

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

Además, me gustaría recomendar refactorización su código de tratar simplemente con la ubicación original del ratón hacia abajo, y la ubicación actual del puntero, en lugar de lidiar con los deltas entre los eventos mouseDragged. Esto podría conducir a resultados inesperados en el futuro.

En su lugar, simplemente almacene el desplazamiento entre el origen de la vista arrastrada y el puntero del mouse (donde el puntero del mouse está dentro de la vista) y establezca el origen del marco en la ubicación del puntero del mouse menos el desplazamiento.

Aquí es un poco de lectura adicional:

Cocoa Drawing Guide

Cocoa Event Handling Guide

0

Creo que se debe calcular de acuerdo con la posición del ratón, hacer que de acuerdo a mi prueba, se vuelve más smooth.Because La forma como a continuación, solo proporciona la posición dentro del sistema de coordenadas de la ventana de la aplicación:

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

W lo que sugiero es algo como esto:

lastDrag = [NSEvent mouseLocation]; 

otros códigos son exactamente iguales.