【问题标题】:setNeedsDisplayInRect: paints a white rectangle onlysetNeedsDisplayInRect:仅绘制一个白色矩形
【发布时间】:2012-03-08 09:14:28
【问题描述】:

我对 CoreGraphics 编程还有些陌生,所以请多多包涵。我正在尝试编写一个应用程序,它允许用户用手指从图像上擦掉东西。我已经确定了基本功能,但结果很慢,因为每次呈现触摸时屏幕都会完全重绘。我做了一些研究,发现使用 UIView 的 setNeedsDisplayInRect: 方法只能刷新屏幕的一部分。

这确实调用了drawRect:正如预期的那样,但是我在drawRect中绘制的所有内容:在setNeedsDisplayInRect:之后被忽略。相反,rect 参数中的区域只是用白色填充。不管我在里面画什么,我最终得到的都是一个白色的矩形。

本质上,这就是我所做的:

1) 当用户触摸屏幕时,这个触摸被渲染成一个遮罩 2) 当drawRect: 被调用时,图像被那个掩码所掩盖

我肯定忽略了一些简单的事情吗?

【问题讨论】:

    标签: iphone core-graphics


    【解决方案1】:

    我找到了一个解决方案,但是我仍然无法理解它是如何工作的。代码如下:

    该方法以同样的方式翻转给定的矩形,其中上下文中的坐标变换翻转了上下文坐标系:

    - (CGRect) flippedRect:(CGRect)rect
    {
        CGRect flippedRect = rect;
    
        flippedRect.origin.y = self.bounds.size.height - rect.origin.y - rect.size.height;
    
        return CGRectIntersection( self.bounds, flippedRect );
    }
    

    这会从触摸位置计算要更新的矩形。请注意,矩形被翻转:

    - (CGRect) updateRectFromTouch:(UITouch *)touch
    {
        CGPoint location = [touch locationInView:self];
    
        int d = RubbingSize;
    
        CGRect touchRect = [self flippedRect:CGRectMake( location.x - d, location.y - d, 2*d, 2*d )];
    
        return CGRectIntersection( self.frame, touchRect );
    }
    

    在渲染触摸中,“翻转”更新矩形被强制:

    - (void) renderTouch:(UITouch *)touch
    {
        //
        // Code to render into the mask here
        //
    
        if ( m_updateRect.size.width == 0 )
        {
            m_updateRect = [self updateRectFromTouch:touch];
        }
        else 
        {
            m_updateRect = CGRectUnion( m_updateRect, [self updateRectFromTouch:touch] );
        }
    }   
    

    在手指绘画过程中,整个视图以大约 20Hz 的频率刷新。以下方法每 1/20 秒调用一次,并提交矩形进行渲染:

    - (void) refreshScreen
    {
        if ( m_updateRect.size.width > 0 )
        {
            [self setNeedsDisplayInRect:[self flippedRect:m_updateRect]];
        }
    }
    

    这是一个比较矩形的辅助方法:

    BOOL rectIsEqualTo(CGRect a, CGRect b)
    {
        return a.origin.x == b.origin.x && a.origin.y == b.origin.y && a.size.width == b.size.width && a.size.height == b.size.height;
    }
    

    在drawRect:方法中,更新矩形仅用于绘制需要更新的部分。

    - (void)drawRect:(CGRect)rect 
    {
        BOOL drawFullScreen = rectIsEqualTo( rect, self.frame );
    
        // Drawing code
    
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        // Turn coordinate system around
    
        CGContextTranslateCTM( context, 0.0, self.frame.size.height );
    
        CGContextScaleCTM( context, 1.0, -1.0 );
    
        if ( drawFullScreen )
        {
            // draw the full thing
            CGContextDrawImage( context, self.frame, self.image );
        }
        else 
        {       
            CGImageRef partialImage = CGImageCreateWithImageInRect( self.image, [self flippedRect:m_updateRect] );
    
            CGContextDrawImage( context, m_updateRect, partialPhoto );
    
            CGImageRelease( partialImage );
        }
    
            ...
    
        // Reset update box
    
        m_updateRect = CGRectZero;
    }
    

    如果有人可以向我解释为什么翻转有效,我将不胜感激。

    【讨论】:

      【解决方案2】:

      翻转问题很可能是因为 UIKit 与 Core Graphics 相比具有“翻转”坐标。

      苹果文档here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-29
        • 2016-10-28
        • 2013-09-03
        相关资源
        最近更新 更多