2

J'ai un NSImage dessiné sur une sous-classe de NSView. Dans une question précédente, on m'a aidé à le redresser dans le coin supérieur gauche. Maintenant, je veux être en mesure de faire pivoter l'image. J'ai un bouton qui incrémente une variable de rotation% 4, et ensuite je la multiplie par -90 pour trouver l'angle de rotation. J'utilise ensuite un NSAffineTransform pour faire pivoter l'image et la traduire sur l'écran. Cependant, il ne semble pas fonctionner comme je le souhaite. J'ai deux problèmes.Rotation d'un NSImage avec ou sans NSAffineTransform

1) Lorsque je fais une rotation, la partie de l'image qui se trouve dans une zone qui n'était pas dans l'image précédente est dessinée correctement. Cependant, la potion qui était précédemment là reste comme l'image originale. Cela signifie qu'après plusieurs rotations, il y a un carré de l'image verticale originale et ensuite un rectangle en dessous ou à gauche de l'image pivotée.

2) Lorsque je redimensionne la fenêtre, l'image se redessine (comme il se doit) dans l'orientation verticale d'origine (comme elle ne devrait pas l'être). Fondamentalement, j'en arrive à la conclusion que NSAffineTransform ne fonctionne pas comme je le pense. Existe-t-il un autre moyen de faire pivoter (et de traduire) l'image? merci

gros morceau de code: (le code entre "WORKS" et "end works" est le code de travail pour dessiner l'image, il vient de ma question précédente).

[CODE ANCIEN SUPPRIME, remplacé plus bas avec le nouveau code]

grâce

EDIT: Un peu plus de recherche trouve qu'au lieu de faire un NSAffineTtransform je peux faire pivoter la vue. Cela semble mieux fonctionner. Cependant, je n'arrive pas à faire fonctionner correctement la traduction. nouveau code ci-dessous (code d'origine supprimé pour économiser l'espace)

- (void)drawRect:(NSRect)rect 
{ 

//WORKS 
    NSRect frame; 
    frame.origin = NSZeroPoint; 
    frame.size = [image size]; 
// end works 

    float deltaX, deltaY, height, width; 

// if the rotate button was just clicked, we need to rotate by 90 deg, otherwise not 
    double rotateDeg = justRot ? -90.0 : 0; 

    justRot = NO; 

// rotate 

    deltaX = 0; 
    deltaY = 0; 

// translate to account for rotation 

    height = [image size].height; 
    width = [image size].width; 

    switch (rotation) 
    { 
     case 0: 
      NSLog(@"No rotation "); 
      break; 
     case 1: 
      deltaX += width; 
      break; 
     case 2: 
      deltaX += width; 
      deltaY += height; 
      break; 
     case 3: 
      deltaY += height; 
      break; 
    } 


    NSPoint orig; 
    if (rotation != 0) 
    { 
     orig.x = -100; 
     orig.y = -100; 
    } 
    [self rotateByAngle: rotateDeg]; 
    NSLog(@"orig %f %f", orig.x, orig.y); 
// WORKS 
    [self setFrame: frame]; 
    [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1]; 
// end works 
    [self translateOriginToPoint: orig];  
} 

Répondre

2

Ok, pour l'histoire, dans le cas où quelqu'un a cette question est ici la réponse que je suis venu avec:

La rotation du cadre reste dans le drawRect, tout le reste passe à la méthode rotate:

-(void)rotate 
{ 
    float deltaX, deltaY, height, width; 

    rotation = (rotation +1) % 4 ; 

    deltaX = 0; 
    deltaY = 0; 

// translate to account for rotation 

    height = [image size].height; 
    width = [image size].width; 

    switch (rotation) 
    { 
     case 0: 
      NSLog(@"No rotation "); 
      deltaY -= width; 
     break; 
     case 1: 
      deltaY -= height; 
      break; 
     case 2: 
      deltaX += height-width; 
      deltaY -= height ; 
      break; 
     case 3: 
      deltaX += height-width; 
      deltaY -= width; 
      break; 
    } 

    NSPoint orig; 
    orig.x = deltaX; 
    orig.y = deltaY; 

    [self rotateByAngle: 90.0]; 
    [self translateOriginToPoint: orig]; 

    [self setNeedsDisplay:YES]; 
} 
1

Je devine que vous souhaitez faire pivoter l'image à propos de son centre. Si c'est le cas, vous devez traduire l'origine de la transformation affine au centre de l'image, puis la faire pivoter, puis la traduire. Maintenant, si vous avez des artefacts de la position previos, c'est probablement parce que vous n'avez pas appelé - [NSView setNeedsDisplayInRect:] avec les rectangles corrects. Rappelez-vous que vous devez invalider à la fois les images précédentes et les nouvelles positions.

Mise à jour: Je viens de remarquer que vous modifiez le cadre de la vue depuis drawRect :. C'est trop tard pour changer le cadre. Au lieu de cela, dessinez l'image à l'emplacement correct sans changer le cadre de la vue.

+0

Eh bien, plutôt que de traduire l'image, puis la retraduire, il est plus facile de simplement traduire l'image pivotée ... Je fais une droite f orward "setNeedsDisplay" sans rect, donc il devrait invalider le tout, non? Modifier le cadre des vues est juste que c'est la bonne forme. de cette façon, quand je change la taille de la fenêtre, il sait où créer des barres de défilement ... –

+0

Je ne pense pas que je l'ai dit assez fortement. Je ne pense pas que changer le cadre d'une vue pendant le tirage rect est supporté.La meilleure preuve que je peux trouver est ici: http://developer.apple.com/releasenotes/Cocoa/AppKit.html. Voir les notes à propos de la vue va dessiner la méthode. Le fait de sortir de leur façon de dire que la modification du cadre pendant viewWillDraw est pris en charge, ce qui implique pour moi de le modifier pendant drawRect: n'est pas supporté. –

+0

hrm, eh bien, il semble fonctionner dans le but de changer le SHAPE du cadre, de sorte que les barres de défilement apparaissent correctement ... mais je pourrais mettre cela dans la méthode de rotation à la place ... il ne semble pas help any ... –