setNeedsDisplayInRect: рисует только белый прямоугольник - PullRequest
3 голосов
/ 06 апреля 2010

Я все еще немного новичок в программировании CoreGraphics, поэтому, пожалуйста, потерпите меня. Я пытаюсь написать приложение, которое позволяет пользователю стирать изображение пальцем. У меня есть основные функциональные возможности, но результат вялый, так как экран полностью перерисовывается при каждом касании. Я провел некоторое исследование и обнаружил, что могу обновить только часть экрана, используя setNeedsDisplayInRect: метод UIView.

Это вызывает drawRect: как и ожидалось, однако все, что я рисую в drawRect: после setNeedsDisplayInRect: игнорируется. Вместо этого область в параметре rect просто заполняется белым. Неважно, что я рисую внутри, все, что у меня получается, это белый прямоугольник.

По сути, это то, что я делаю:

1) когда пользователь касается экрана, это касание отображается в маске 2) когда вызывается drawRect: изображение маскируется этой маской

Должно быть, я что-то упускаю из виду, не так ли?

Ответы [ 2 ]

2 голосов
/ 13 апреля 2010

Я нашел решение, однако оно все равно ускользает от меня, как именно это работает.Вот код:

Этот метод переворачивает данный прямоугольник таким же образом, при котором преобразование координат в контексте переворачивает систему координат контекста:

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

Весь вид обновляется с частотой около 20 Гц в процессе рисования пальцем.Следующий метод вызывается каждые 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;
}

Если кто-то может объяснить мне, почему переворачивание работает, я был бы признателен.

1 голос
/ 08 марта 2012

Проблема переворачивания наиболее вероятна, потому что UIKit имеет «перевернутую» координату по сравнению с Core Graphics.

Документация Apple здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...