所以,我的 Cocoa 应用程序中遇到了这个奇怪的问题。一个工具栏项,和一些 NSImageViews 只是渲染他们的图像颠倒,没有明显的原因。当我出于某种原因启动应用程序时,工具栏项目实际上是这样的(图标是在代码中分配的),然后,当我使用取景器缩放效果打开HUD时,其中包含的 ImageView 是颠倒的。
上面的图片是这种奇怪现象的屏幕截图。正如您所看到的,HUD 中的每个 NSImageView 中的“显示垃圾”项旋转得很奇怪,但 NSBrowser 中的 NSImageView 没有问题。
我该如何追踪导致此问题的原因,然后进行修复?
最佳答案
参见Mac OS X Developer Release Note - AppKit Release Notes (Snow Leopard) :
Flipped images in toolbars (New since January 2009 seed)
A common but incorrect practice is to call
setFlipped:YES
on an image that you plan to draw into a flipped graphics context. This is incorrect because if the image is later drawn into a normal unflipped context, the image will appear upside down. However, Leopard and earlier contained a bug in which images set onNSToolbarItem
(viasetImage:
) would ignore theirisFlipped
property. SnowLeopard fixes this bug for apps compiled on SnowLeopard with the 10.6 SDK; as a result, some images which should have drawn upside down in Leopard, will begin doing so when your app is recompiled.If you recompile your app on SnowLeopard and discover that your toolbar item images are drawing upside down, then it indicates that you are calling
setFlipped:YES
somewhere within your code. You should remove those calls and replace the image drawing with methods that correctly handle flipped contexts. See the discussion ofsetFlipped:
in these Release Notes for more discussion.
回复:setFlipped:
NSImage: deprecating -[NSImage setFlipped:], adding a drawing method that respects context flippedness (New since WWDC 2008)
The flipped attribute of
NSImage
is widely misunderstood. We are deprecating it for SnowLeopard, and replacing its typical uses with less error-prone API.The property describes the orientation of the internal coordinate system of the
NSImage
. Just as a superview never cares about the flippedness of its subviews, a user of anNSImage
should not care about its flippedness.The typical (flawed) use case is to try to call
[image setFlipped:[[NSGraphicsContext currentContext] isFlipped]]
just prior to drawing, but this does not accomplish the intended goal. If called before caching, then representations end up caching upside down, and the flip is absorbed into the cache. If called after caching, it has no effect-the cached representation is already supposed to incorporate any necessary flipping. In the former case, if theNSImage
is drawn anywhere else later, it ends up upside down in that place, which is also confusing because the bug and the expression of the bug are far apart. Lack of understanding regarding flippedness is also frequently the source of poorly performing code, in which people make unnecessary intermediate buffers to work around perceived framework bugs. The framework behaves according to design, but contrary to expectation, and the semantics are not all that useful. It's also difficult to change the semantics of-[NSImage isFlipped]
, because a lot of code is very closely dependent on the current behavior. Rather than attempt this, we have deprecated the property.We are providing a simple and correct way to draw images in a flipped or unflipped context, which is a draw method that can account for context flippedness. We are also adding a hints parameter matching the hints in
-bestRepresentationForRect:context:hints:
.
- (void)drawInRect:(NSRect)dstRect fromRect:(NSRect)srcRect operation:(NSCompositingOperation)op fraction:(CGFloat)alpha respectFlipped:(BOOL)respectContextIsFlipped hints:(NSDictionary *)hints;
Pass
YES
forrespectFlipped
to get the fancy new behavior. One note for those that understand the CTM and worry that this method has an odd interaction, where modifying the CTM could fail to have any effect on image drawing: This is not the case. This method branches behavior based on[[NSGraphicsContext currentContext] isFlipped]
. Modifying the CTM might turn your axes upside down, but it will not alter the result of-[NSGraphicsContext isFlipped]
. They're completely orthogonal.A second valid use of
-[NSImage setFlipped:]
was to specify the flippedness of the context obtained via-[NSImage lockFocus]
. There are cases, for example drawing directly viaNSLayoutManager
, that require a flipped context. To cover this case, we add
- (void)lockFocusFlipped:(BOOL)flipped;
This doesn't alter the state of the image itself, only the context on which focus is locked. It means that (0,0) is at the top left and positive along the Y-axis is down in the locked context.
关于cocoa - NSImageViews 中的图像随机颠倒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4754973/