2009-07-08 5 views
1

J'ai une sous-classe de NSView, et je dessine un NSImage. Je désactive NSAffineTransforms pour faire pivoter, traduire et redimensionner l'image.NSAffineTransforms n'est pas utilisé?

La plupart fonctionnent correctement. Cependant, parfois, les transformations ne semblent pas activées.

Par exemple, lorsque je redimensionne la fenêtre, la transformation de rotation ne se produit pas. Lorsque j'effectue un zoom avant sur l'image, elle place le coin inférieur gauche de l'image au bon endroit, mais ne le fait pas, mais il fait un zoom sur la partie de l'image qui serait à droite de l'original image de taille. Si je le fais pivoter, il effectue un zoom correct, mais traduit mal. (Le transation peut être une erreur de calcul de ma part)

Voici le code de mon drawRect: (désolé pour le long morceau de code)

- (void)drawRect:(NSRect)rect 
{ 
    // Drawing code here. 
    double rotateDeg = -90* rotation; 
    NSAffineTransform *afTrans = [[NSAffineTransform alloc] init]; 
    NSGraphicsContext *context = [NSGraphicsContext currentContext]; 
    NSSize sz; 
    NSRect windowFrame = [[self window] frame]; 
    float deltaX, deltaY; 
    NSSize superSize = [[self superview] frame].size; 
    float height, width, sHeight, sWidth; 

    NSRect imageRect; 

    if(image) 
    { 
     sz = [ image size]; 
     imageRect.size = sz; 
     imageRect.origin = NSZeroPoint; 
     imageRect.size.width *= zoom; 
     imageRect.size.height *= zoom; 

     height = sz.height * zoom ; 
     width = sz.width *zoom ; 
     sHeight = superSize.height; 
     sWidth = superSize.width; 
    } 

je dois saisir les tailles de tout début afin que Je peux les utiliser plus tard quand je tourne. Je ne suis pas sûr que je dois protéger tout cela, mais je suis paranoïaque des années de C ...

[context saveGraphicsState]; 

// rotate 
    [afTrans rotateByDegrees:rotateDeg]; 
// translate to account for window size; 
    deltaX = 0; 
    deltaY = 0; 

// translate to account for rotation 

// in 1 and 3, X and Y are reversed because the entire FRAME 
// (inculding axes) is rotated! 
    switch (rotation) 
    { 
     case 0: 
//   NSLog(@"No rotation "); 
      break; 
     case 1: 
      deltaY -= (sHeight - height); 
      deltaX -= sHeight ; 
      break; 
     case 2: 
      deltaX -= width; 
      deltaY -= (2*sHeight - height);  
      // it's rotating around the lower left of the FRAME, so, 
      // we need to move it up two frame hights, and then down 
      // the hieght of the image 
      break; 
     case 3: 
      deltaX += (sHeight - width); 
      deltaY -= sHeight; 
      break; 
    } 

Depuis que je suis en rotation autour du coin en bas à gauche, et je veux que l'image soit verrouillé dans le coin supérieur gauche, j'ai besoin de déplacer l'image autour. Quand je tourne une fois, l'image est dans le quadrant +, donc j'ai besoin de la déplacer d'une hauteur de vue, et à gauche une hauteur de vue moins une hauteur d'image. etc.

[afTrans translateXBy:deltaX yBy:deltaY]; 

// for putting image in upper left 

// zoom 
    [afTrans scaleBy: zoom]; 
    printMatrix([afTrans transformStruct]); 
    NSLog(@"zoom %f", zoom); 
    [afTrans concat]; 

    if(image) 
    { 
     NSRect drawingRect = imageRect; 
     NSRect frame = imageRect; 

     frame.size.height = MAX(superSize.height, imageRect.size.height) ; 
     [self setFrame:frame]; 

     deltaY = superSize.height - imageRect.size.height; 
     drawingRect.origin.y += deltaY; 

Cela donne à la trame la taille correcte pour que l'image soit dans le coin supérieur gauche du cadre. Si l'image est plus grande que la fenêtre, je veux que le cadre soit assez grand pour que les barres de défilement apparaissent. Si ce n'est pas le cas, je veux que le cadre soit assez grand pour qu'il atteigne le haut de la fenêtre.

 [image drawInRect:drawingRect 
       fromRect:imageRect 
       operation:NSCompositeSourceOver 
       fraction:1]; 

     if((rotation %2)) 
     { 
      float tmp; 
      tmp = drawingRect.size.width; 
      drawingRect.size.width = drawingRect.size.height; 
      drawingRect.size.height = tmp; 
     } 

Ce code peut être tout à fait historique, maintenant que je regarde ... l'idée était d'échanger la hauteur andwidth si je rotation de 90 ou 270 DEGS.

} 
    else 
     NSLog(@"no image"); 

    [afTrans release]; 
    [context restoreGraphicsState]; 

} 
+0

Pourriez-vous diviser le gros bloc de code en sections plus petites et essayer d'expliquer ce que vous essayez de faire dans chacun (en particulier l'instruction de commutation pour la rotation et les deux blocs if (image)). J'ai votre code dans un projet, mais j'ai du mal à suivre ce que vous faites. – Peter

+0

Ok, pas de problème! –

Répondre

0

Pourquoi utilisez-vous la taille de l'aperçu? C'est quelque chose dont vous ne devriez presque jamais avoir à vous soucier. Vous devez faire en sorte que la vue fonctionne de manière indépendante sans être dépendante de l'intégration dans une vue spécifique.

Réduire la taille de imageRect n'est probablement pas la bonne solution. Généralement, lorsque vous appelez -drawImage, vous voulez que le rectangle source soit les limites de l'image et que le rectangle de destination soit mis à l'échelle pour le zoomer.

Les problèmes que vous signalez sont de type sonore, car vous ne redessinez pas l'intégralité de la vue après avoir modifié la transformation. Appelez -setNeedsDisplay: YES?

Comment cette vue est-elle intégrée dans la fenêtre? Est-il à l'intérieur d'un NSScrollView? Avez-vous vérifié que la vue déroulante se redimensionne avec la fenêtre?

+0

J'ai besoin de la taille de l'aperçu parce que sinon je ne sais pas où se trouve le coin supérieur gauche. Je veux que mon image soit verrouillée en haut à gauche, pas en bas à gauche.Je peux PROBABLEMENT m'éloigner de ceci en utilisant la méthode isFlipped mais je pensais que cette façon était plus propre quand j'ai commencé ... Je peux essayer de faire la mise à l'échelle entièrement avec le drawRect, ça vaut la peine d'essayer au moins, mais j'utilise needsDisplay: YES et la vue est dans un défilement qui est verrouillé à la taille de la fenêtre. –

Questions connexes