NSRect et images
muqaddar
Administrateur
Salut,
J'ai un truc bizarre ici :
Alors, j'ai un timer qui appelle afficheFrame, elle même qui appelle drawRect.
img est une variable d'instance.
Le NSLog de afficheFrame me renvoie bien l'image, mais pas celui de drawRect, pourtant img est bien var d'instance, et je la release après setNeedDisplay...
Le pire c'est que ça marchait avant...
Une idée ?
J'ai un truc bizarre ici :
/<br />- (void)drawRect:(NSRect)rect<br />{<br /> [[NSColor clearColor] set];<br /> NSRectFill([self frame]);<br />NSLog(@"img : %@", img);<br /> [img compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver];<br />}<br /><br /><br />- (void)afficheFrame: (NSTimer *)myTimer<br />{ <br /> img = [[customFramesArray objectAtIndex: lastImg] retain];<br /> [self setNeedsDisplay:YES];<br /> NSLog(@"img : %@", img);<br /> [img release];<br /> <br /> lastImg++;<br /> <br /> if (lastImg == [defaultFramesArray count]) {<br /> [timer invalidate];<br /> [timer release];<br /> }<br />}
Alors, j'ai un timer qui appelle afficheFrame, elle même qui appelle drawRect.
img est une variable d'instance.
Le NSLog de afficheFrame me renvoie bien l'image, mais pas celui de drawRect, pourtant img est bien var d'instance, et je la release après setNeedDisplay...
Le pire c'est que ça marchait avant...
Une idée ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
fastoche la gestion mémoire en ObjC hein ? ;D
Pareil... y'a un truc qui m'échappe, le NSLog de drawRect me renvoie un seul (null) alors que afficheFrame est appelé 30 fois, donc drawrect aussi par le biais de setNeedDisplay...
C'est pas hyper dur une fois qu'on a pigé les grands principes.
les images sont retenus par ton tableau
T'as raison ! ;D
Oui, tu as raison, j'en ai pas besoin apparemment.
Néanamoins le pb persiste. drawRect est appellée une seule fois !! alors que afficheFrame 30 fois.
Je ne sais pas si ça répond à ta question
Excuse-moi, j'ai une question bête, qui n'a rien à voir avec la mémoire, mais setNeedsDisplay:YES ne provoque pas l'affichage, il le marque simplement comme nécessaire au prochain runloop de l'interface ?
Donc si afficheFrame est appelé 30 fois dans une boucle for(...) quelconque, et bien le réaffichage ne sera pas fait 30 fois, mais une seule, après que la boucle for a terminé et qu'on repasse au runloop du programme.
Il faudrait rajouter un [self displayIfNeeded] après le [self setNeedsDisplay:YES], non ?
+
Chacha
Oui, ou alors [self display], et l'on n'a plus besoin du [self setNeedsDisplay:YES];
Et non, img n'est tjs pas reconnu ds drawRect...
Une idée en passant : ta NSView est-elle subView d'autre chose (NSBox, NSScrollView...) ? je crois qu'une fois j'ai eu un problème similaire d'affichage récalcitrant, et que je m'en étais sorti en faisant un setNeedsDisplay (et un displayIfNeeded) sur les superviews !
Si tu es une sous-vue de NSBox, essaye
[self setNeedsDisplay:YES];
[[self superview] displayIfNeeded:YES];
et si tu es sous-vue de NSScrollView:
[self setNeedsDisplay:YES];
[[[self superview] superview] displayIfNeeded:YES];
Je en me rappelle pas le contexte dans lequel j'ai fait cela, mais au final ce code avait disparu, donc avait dû être résolu d'une autre manière. Mais si ça peut aider...
+
Chacha
Cette classe est initialisée depuis ma classe controlleur... si ça peut être une piste...
[tt]
- (void)afficheFrame: (NSTimer *)myTimer
{
[self lockFocus];
img = [[customFramesArray objectAtIndex: lastImg] retain];
[self setNeedsDisplay:YES];
[self unlockFocus];
[/tt]
Il appécie pas du tout :
2005-03-03 18:41:18.838 iApp[11634] *** NSTimer discarding exception 'NSInternalInconsistencyException' (reason 'lockFocus sent to a view whose window is deferred and does not yet have a corresponding platform window') that raised during firing of timer with target 350b60 and selector 'afficheFrame:'
2005-03-03 18:41:18.878 iApp[11634] *** Assertion failure in -[MyView lockFocus], AppKit.subproj/NSView.m:2746
Avant le [self unlockFocus], tu peux aussi mettre :
[tt]
[[NSGraphicsContext currentContext] flushGraphics];
[/tt]
[tt]
(void)afficheFrame: (NSTimer *)myTimer
{
[self lockFocus];
img = [customFramesArray objectAtIndex: lastImg];
[[NSColor clearColor] set];
NSRectFill([self frame]);
fait son effet et drawRect est bien appelé en boucle.
Par contre mon image s'affiche pas...
[tt]Â
-(void)afficheFrame: (NSTimer *)myTimer
{
img = [customFramesArray objectAtIndex: lastImg];
[self setNeedsDisplay:YES];
[[NSGraphicsContext currentContext] flushGraphics];
[/tt]
Mes images apparaissent, mais le pb c'est que maintenant elles écrasent pas les anciennes. Elles apparaissent toutes mais comme j'ai un canal alpha, et bien, elles se montent les unes sur les autres...
Pourtant ça :
[[NSColor clearColor] set];
NSRectFill([self frame]);
C'est bien fait pour nettoyer le drawRect non ?
[NSBezierPath fillRect:[self frame]];
essaye plutôt NSRectFill([self bounds])
et pourquoi pas NSRectFill(rect);
Il n'y a aucune différences, je n'ai jamais eu l'honneur de voir le code de cette fonction, mais je pense qu'elle se contente juste d'appeler NSBezierPath.
Bon, merci à vous, j'ai compris mon erreur.
J'ai définie ma sous-classe de NSView dans IB sur une customView et je créais aussi une instance depuis mon controlleur !!! ça se montait dessus, c'était le bordel. En plus j'instanciais init et non initWithFrame.
Encore merci de vos réponses réactives.