3

所以,我的 Cocoa 应用程序中有这个奇怪的问题。一个工具栏项和一些 NSImageViews 只是无缘无故地颠倒了他们的图像。当我出于某种原因启动应用程序时,工具栏项实际上是这样出现的(图标是在代码中分配的),然后,当我用取景器缩放效果打开我的 HUD 时,其中包含的 imageViews 是颠倒的。

替代文字

上图是这个奇怪现象的截图。如您所见,“显示垃圾箱”项目奇怪地旋转,HUD 中的每个 NSImageView,但 NSBrowser 中的 NSImageView 很好。

我将如何去追踪造成这种情况的原因,然后修复它?

4

2 回答 2

13

请参阅Mac OS X 开发人员发行说明 - AppKit 发行说明(雪豹)

工具栏中的翻转图像(自 2009 年 1 月种子以来新增)

一种常见但不正确的做法是调用setFlipped:YES您计划绘制到翻转图形上下文中的图像。这是不正确的,因为如果稍后将图像绘制到正常的未翻转上下文中,则图像将上下颠倒。然而,Leopard 和更早的版本包含一个错误,其中设置在 NSToolbarItem(via setImage:) 上的图像会忽略它们的isFlipped属性。SnowLeopard 为使用 10.6 SDK 在 SnowLeopard 上编译的应用程序修复了此错误;因此,一些本应在 Leopard 中颠倒绘制的图像将在重新编译您的应用程序时开始这样做。

如果您在 SnowLeopard 上重新编译您的应用程序并发现您的工具栏项图像是颠倒的,则表明您setFlipped:YES在代码中的某个位置调用。您应该删除这些调用并用正确处理翻转上下文的方法替换图像绘制。有关更多讨论,请参阅setFlipped:这些发行说明中的​​讨论。

关于:setFlipped:

NSImage:弃用 -[NSImage setFlipped:],添加尊重上下文翻转的绘图方法(自 WWDC 2008 以来新增)

的翻转属性NSImage被广泛误解。我们正在弃用它的 SnowLeopard,并用不易出错的 API 替换它的典型用途。

该属性描述了内部坐标系的方向NSImage。正如 superview 从不关心其子视图的翻转性一样,an 的用户NSImage 也不应该关心它的翻转性。

典型的(有缺陷的)用例是尝试[image setFlipped:[[NSGraphicsContext currentContext] isFlipped]]在绘图之前调用,但这并没有达到预期的目标。如果在缓存之前调用,则表示最终会颠倒缓存,并且翻转被吸收到缓存中。如果在缓存之后调用,它没有任何效果——缓存的表示已经被认为包含了任何必要的翻转。在前一种情况下,如果NSImage稍​​后在其他任何地方绘制 ,它最终会地方,这也令人困惑,因为 bug 和 bug 的表达相距甚远。对翻转性缺乏了解也是导致代码性能不佳的原因,人们在其中制作了不必要的中间缓冲区来解决感知到的框架错误。该框架的行为符合设计,但与预期相反,语义并不是那么有用。也很难改变 的语义-[NSImage isFlipped],因为很多代码都非常依赖于当前的行为。我们没有尝试这样做,而是弃用了该属性。

我们提供了一种简单而正确的方法来在翻转或未翻转的上下文中绘制图像,这是一种可以解释上下文翻转的绘制方法。我们还添加了一个与 中的提示匹配的提示参数-bestRepresentationForRect:context:hints:

- (void)drawInRect:(NSRect)dstRect fromRect:(NSRect)srcRect operation:(NSCompositingOperation)op fraction:(CGFloat)alpha respectFlipped:(BOOL)respectContextIsFlipped hints:(NSDictionary *)hints;

通过YESrespectFlipped获得花哨的新行为。对于那些了解 CTM 并担心此方法具有奇怪的交互作用的人的一个注意事项,其中修改 CTM 可能无法对图像绘制产生任何影响:情况并非如此。此方法基于 [[NSGraphicsContext currentContext] isFlipped]. 修改 CTM 可能会使您的坐标轴颠倒,但不会改变 -[NSGraphicsContext isFlipped]. 它们是完全正交的。

的第二个有效用途-[NSImage setFlipped:]是指定通过-[NSImage lockFocus]. 在某些情况下,例如直接通过 绘图NSLayoutManager,需要翻转上下文。为了涵盖这种情况,我们添加

- (void)lockFocusFlipped:(BOOL)flipped;

这不会改变图像本身的状态,只会改变焦点锁定的上下文。这意味着 (0,0) 在左上角,沿 Y 轴的正值在锁定上下文中向下。

于 2011-01-21T04:07:04.417 回答
3

我不以为然的猜测是图像错误地-setFlipped:YES调用了它。

于 2011-01-21T04:01:49.753 回答