2009-08-18 28 views
2

我在NSView的子类上绘制了NSImage。在之前的问题中,我被帮助在左上角直立。现在,我希望能够旋转图像。我有一个按钮,增加一个旋转变量%4,然后我乘以-90找到旋转角度。然后我使用NSAffineTransform来旋转图像,并将其翻译回屏幕上。但是,它似乎没有按照我期望的方式工作。我有两个问题。在NSAffineTransform中旋转NSImage

1)当我旋转时,图像中不在前一帧中的部分被正确绘制。然而,以前那里的魔药仍然是原始图像。这意味着经过多次旋转后,原始直立图像有一个正方形,然后是旋转图像左下方的矩形。

2)当我重新调整窗口大小时,图像会以原始直立方向重新绘制(因为它应该)(因为它不应该)。

基本上,我得出的结论是,NSAffineTransform不按我认为的方式工作。是否有其他方式来旋转(并翻译)图像?谢谢

大码块:(“WORKS”和“end works”之间的代码是工作代码,只是画出图像,它来自我的上一个问题)。

[老代码删除,更换新代码下]

感谢

编辑:一点多的研究发现,而不是做一个NSAffineTtransform我可以旋转视图。这似乎更好。但是,我无法让翻译工作得很好。下面的新代码(原代码删除,以节省空间)

- (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];  
} 

回答

2

好,对历史,如果任何人在这里有这个问题是我想出答案:

的框架旋转停留在drawRect中,其他的一切移动到旋转方法:

-(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

我猜你想旋转图像的中心。如果是这样,您需要将仿射变换的原点转换为图像的中心,然后旋转,然后转回。现在,如果您有遗留前置位置的工件,可能是因为您没有用正确的矩形调用 - [NSView setNeedsDisplayInRect:]。请记住,您需要使图像的上一个和新位置都无效。

更新:我只是注意到,你正在从drawRect:内改变视图的框架。现在改变框架为时已晚。相反,请在不改变视图框架的情况下在正确的位置绘制图像。

+0

好,而不是图像转换,然后将其转换回,它更容易只是平移旋转的图像... 我做了直的f无条件地向后“setNeedsDisplay”,所以它应该使整个事情无效,不是? 更改视图框架就是这样,它是正确的形状。这种方式,当我改变窗口的大小,它知道在哪里创建滚动条... – 2009-08-18 18:10:16

+0

我不认为我说得够强。我不认为在绘制矩形时更改视图的框架是受支持的。我可以在这里找到最好的支持证据:http://developer.apple.com/releasenotes/Cocoa/AppKit.html。请参阅关于视图的说明将绘制方法。我们支持在viewWillDraw期间改变框架,这对我来说意味着不支持在drawRect中更改它。 – 2009-08-18 19:14:11

+0

hrm,好吧,它似乎工作的目的是为了改变框架的形状,以便滚动条出现正确...但我可以把它放入旋转方法,而不是......它似乎并不帮助任何... – 2009-08-18 20:08:15