11
votes

Dessiner progressivement dans un UIView (iPhone)

Autant que j'ai compris jusqu'à présent, chaque fois que j'attire quelque chose dans le drawrect: d'un UIView, tout le contexte est effacé puis redessiné.

Donc, je dois donc faire quelque chose comme ça pour dessiner une série de points:

Méthode A: Dessinez tout sur chaque appel xxx

ce qui signifie que je dois stocker tous mes points ( C'est bien) et les ré-dessinez tous, un par un, chaque fois que je veux ajouter un nouveau. Malheureusement, cela donne à mes terribles performances et je suis sûr qu'il y a une autre façon de le faire, plus efficacement.

EDIT: Utiliser le code de MRMAGE, j'ai fait ce qui suit, qui est malheureusement aussi lent et que la couleur se mélangeait 'T Travailler. Toute autre méthode que je pourrais essayer?

Méthode B: Enregistrement des dessins précédents dans un uiImage et dessinez uniquement les nouveaux trucs et cette image xxx

EDIT: Après tout, j'ai combiné l'une des méthodes mentionnées ci-dessous avec redessiner uniquement dans le nouveau recto. Le résultat est: Méthode rapide: xxx

merci tout le monde!


0 commentaires

5 Réponses :


0
votes

Combien d'ellipses allez-vous dessiner? En général, les graphismes principaux devraient pouvoir attirer rapidement beaucoup d'ellipses rapidement.

Vous pouvez cependant mettre en cache vos anciens dessins à une image (je ne sais pas si cette solution est plus performante, toutefois): P >

UIGraphicsBeginImageContext(self.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext(); // ctx is now the image's context

[cachedImage drawAtPoint:CGPointZero];
// only plot new ellipses here...

[cachedImage release];
cachedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextDrawImage(context, self.bounds, maskRef);          //draw the mask
CGContextClipToMask(context, self.bounds, maskRef);         //respect alpha mask
CGContextSetBlendMode(context, kCGBlendModeColorBurn);      //set blending mode

[cachedImage drawAtPoint:CGPointZero];


5 commentaires

Je ne dessine pas beaucoup, disons-nous environ 100. Mais avec le travail supplémentaire (dessinant une image sur chaque traction: et masquant les ellipses dessus), il est lent, même sur un 3GS.


Vous pouvez également essayer de masquer après avoir peint les ellipses (peut-être en dessinant d'abord à un tampon, puis en tirant de la mémoire tampon sur votre vue).


Dans le code ci-dessus, vous dites "CTX" mais signifie "contexte" non? J'essaie de voir votre méthode maintenant de voir si cela fait une différence.


Non, votre code ne fonctionne pas droit. Je violerai un peu avec elle en utilisant un uiimage pour stocker le contenu de mon contexte.


J'ai édité ma question initiale pour inclure la mise en œuvre à l'aide de vos conseils. Malheureusement, c'est juste aussi lent ...



6
votes

Si vous ne changez que une petite partie du contenu de UIVIEW chaque fois que vous dessinez (et que le reste du contenu reste le même), vous pouvez l'utiliser. Plutôt que de redessiner tout le contenu de l'UIView chaque fois que vous pouvez marquer uniquement les zones de la vue qui ont besoin de redessiner à l'aide de - [uiview SetNeedsDisplayInrect:] au lieu de - [UIView SetNeedsDisplay] < / code>. Vous devez également vous assurer que le contenu graphique n'est pas effacé avant de dessiner en réglant View.clearScontextBeforeRawing = Oui;

Bien sûr, tout cela signifie également que votre Drawrect: La mise en œuvre doit respecter le paramètre rectoire, qui devrait alors être une petite sous-section de la section de votre version complète (à moins que quelque chose d'autre accueille le recto complet) et ne tirer que dans cette partie.


2 commentaires

Si " View.ClearStextExtBeforeRawing = non; " a fait ce qu'il dit dans la documentation qu'il devrait faire, tout le dessin devrait être incrémental, non? Mais ce n'est pas ...


Votre dessin n'est pas incrémental, sauf si vous vous assurez que votre drawrect: la mise en œuvre ne dessine que les sections mises à jour. Le moyen standard de marquer "sections mises à jour" (sections sales) utilise SetNeedsDisplayInrect :. Si vous définissez ClearScontentBeforeRawing = Non, puis remplissez tout le contexte avec le contenu de toute façon, votre prestation de performance est petite.



2
votes

Vous pouvez enregistrer votre CGPath en tant que membre de votre classe. Et utilisez-le dans la méthode de tirage, vous devez créer uniquement le chemin lorsque les points changent, mais pas à chaque fois que la vue est redessinée, si les points sont incrémentiels, continuez simplement à ajouter les ellipses au chemin. Dans la méthode Drawrect, il vous suffira d'ajouter le chemin

CGContextAddPath(context,dotsPath);

-(CGMutablePathRef)createPath
{
    CGMutablePathRef dotsPath =  CGPathCreateMutable();

    for (Drop *drop in myPoints) {
        CGPathAddEllipseInRect ( dotsPath,NULL,
            CGRectMake(drop.point.x - drop.size/2, drop.point.y - drop.size/2, drop.size, drop.size));
    }

return dotsPath;
}


2 commentaires

Vient d'essayer ça aussi. Cela pourrait être un peu plus rapide que les autres méthodes, mais c'est toujours assez lent. Je vais essayer de le combiner avec le tiroir: méthode et voyez si cela le fait. Merci.


Les classes de l'objectif-C n'ont pas de "membres", ils ont des variables d'instance, ou "ivars".



1
votes

Si je comprends votre problème correctement, j'essaierais de dessiner à un cgbitmapcontext au lieu de l'écran directement. Ensuite, dans le drawrect , dessinez uniquement la partie du bitmap pré-rendu nécessaire à partir du paramètre rect .


2 commentaires

Je n'ai rien essayé comme ça. Je vais probablement essayer d'essayer. Si vous avez un code qui montre comment cela est fait, je l'apprécierais.


++ C'est ma méthode de choix. Je viens de blt le tout. Il élimine le clignotant et donne l'illusion de dessiner instantanément.



0
votes

Si vous êtes capable de mettre en cache le dessin comme une image, vous pouvez profiter du support de corniment d'UIVIEW. Ce sera beaucoup plus rapide que d'utiliser Quartz, car Quartz fait son dessin dans des logiciels. XXX


0 commentaires