voir un dessin se faire à l'écran ...
macvelotte
Membre
Bonjour à tous ...
Je dessine point par point un triangle de Sierpinski (triangle fractal). Voici comment est fait le dessin (S1,S2,S3 sont les sommets du triangle) :
Il ne se passe rien à l'écran tant que "tracer" n'est pas terminé, après quoi le triangle apparà®t entièrement dessiné.
J'aimerais voir le triangle apparaà®tre progressivement : est-ce possible ? (ce que je faisais en C, CodeWarrior).
Je dessine point par point un triangle de Sierpinski (triangle fractal). Voici comment est fait le dessin (S1,S2,S3 sont les sommets du triangle) :
<br />-(void)tracer<br />{<br /> NSPoint PC;<br /> long total;<br /> [[NSColor whiteColor] set];<br /> int s;<br /> total=0;<br /> do<br /> {<br /> s = (random() % 3)+1;<br /> switch(s)<br /> {<br /> case 1:<br /> {<br /> PC.x=(S1.x+P0.x)/2;<br /> PC.y=(S1.y+P0.y)/2;<br /> break;<br /> }<br /> case 2:<br /> {<br /> PC.x=(S2.x+P0.x)/2;<br /> PC.y=(S2.y+P0.y)/2;<br /> break;<br /> }<br /> case 3:<br /> {<br /> PC.x=(S3.x+P0.x)/2;<br /> PC.y=(S3.y+P0.y)/2;<br /> break;<br /> }<br /> }<br /> [NSBezierPath strokeLineFromPoint:PC toPoint:NSMakePoint(PC.x+0.1,PC.y+0) ];<br /> P0.x=PC.x;<br /> P0.y=PC.y;<br /> total++;<br /> }<br /> while (total<400000);<br /> <br />}<br />
Il ne se passe rien à l'écran tant que "tracer" n'est pas terminé, après quoi le triangle apparà®t entièrement dessiné.
J'aimerais voir le triangle apparaà®tre progressivement : est-ce possible ? (ce que je faisais en C, CodeWarrior).
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Après ton [NSBezierPaht stroke...], fais un [maVue setNeedDisplay].
a+
Non, il doit faire un [maVue display] pour un affichage immédiat.
setNeedDisplay marque la vue comme étant à redessiner... plus tard (c'est à dire en fin de boucle d'événement généralement).
.
un display tout court ::)
Le dessin se fait dans une "StretchView" : je dois être à coté de la plaque ???
Il faut donc réadapter le code que je t'avais donné pour faire boucler la méthode drawRect sur l'appel à la méthode tracer tant que le total de points n'est pas atteint. Encore une fois, le code ci-dessous n'a pas du tout été essayé, donc il y a sûrement de la mise au point à faire...
Il faut déclarer les variables d'instances forceDisplay et total dans l'interfaçage.
[tt]
-(void)awakeFromNib
{
   forceDisplay=NO;
   total=0;
   clicksCount=4;
   [self setNeedsDisplay:YES];
}
-(void)drawRect:(NSRect)rect
{
  NSGraphicsContext *contexte;
  if (!forceDisplay)
  {
  if (clicksCount==4) // Pour l'initialisation
  {
    [[NSColor whiteColor] set];
    NSRectFill(NSMakeRect(rect)); // Initialiser la vue
    return;
  }
  if (clicksCount==0)
  {
    [[NSColor whiteColor] set];
    NSRectFill(NSMakeRect(rect)); // Réinitialiser la vue
    S1=posSouris;
    clicksCount=1;
  }
  if (clicksCount==1)
  {
    S2=posSouris;
    clicksCount=2;
  }
  if (clicksCount==2)
  {
    S3=posSouris;
    clicksCount=3;
  }
 Â
  // Désactivation de l'anti-aliasing
  contexte=[NSGraphicsContext currentContext];
  [contexte setShouldAntialias:NO];
  }
  if (clicksCount<3 && forceDisplay==NO)
  {
    [NSBezierPath strokeLineFromPoint:NSMakePoint(posSouris.x+0.5,posSouris.y) toPoint:NSMakePoint(posSouris.x+0.5,posSouris.y+0.5)];
  }
  else
  {
     clicksCount=0;
     [self tracer]
  }
  if (!forceDisplay)
  {
  // Réactivation de l'anti-aliasing
  contexte=[NSGraphicsContext currentContext];
  [contexte setShouldAntialias:YES];
  }
}
-(void)mouseDown:(NSEvent *)event
{
  if (clicksCount==4)
  {
     clicksCount=0;
  }
  posSouris=[self convertPoint:[event locationInWindow] fromView:nil];
  [self setNeedsDisplay:YES];
  [super mouseDown:event];
}
-(void)tracer
{
  NSPoint PC;
  long total;
  [[NSColor whiteColor] set];
  int s;
  do
   {
     s = (random() % 3)+1;
     switch(s)
      {
      case 1:
        {
         PC.x=(S1.x+P0.x)/2;
         PC.y=(S1.y+P0.y)/2;
         break;
        }
      case 2:
        {
         PC.x=(S2.x+P0.x)/2;
         PC.y=(S2.y+P0.y)/2;
         break;
        }
      case 3:
        {
         PC.x=(S3.x+P0.x)/2;
         PC.y=(S3.y+P0.y)/2;
         break;
        }
      }
     [NSBezierPath strokeLineFromPoint:PC toPoint:NSMakePoint(PC.x+0.1,PC.y+0) ];
     P0.x=PC.x;
     P0.y=PC.y;
     total++;
if (total<400000)
{
     forceDisplay=YES;
     [self display];
}
   }
  while (total<400000);
  total=0;
  forceDisplay=NO;
}[/tt]
quid de "[self display] " ? Cela suppose une "procedure" (j'utilise mal à propos le langage pascal) du type -(void)display ...?
Cette méthode sera appelé automatiquement lorsque ta vue doit être rafraichie (ex : redimensionnement de fenêtre, passage arrière plan/premier plan de l'appli, etc).
Donc faire un [self display] dans le DrawRect de ta vue reviendrai à indiquer qu'il faut appeler le drawRect....
Question : quel est le rôle de l'anti-aliasing >:(
Ca c'est à mesurer...et puis si tu as meilleur méthode et bien je suis preneur...;)
L'anti-aliasing estompe le crénelage en recalculant des couleurs intermédiaires, à toi de voir si tu veux le laisser actif ou non, mais je trouve qu'il est plus pratique de le laisser désactivé au moins pour le dessin des sommets choisis a la souris.
Une piste à explorer serait d'utiliser les methodes:
self window] restoreCachedImage]; //Dessine l'image sauvegardée par cacheImageInRect<br />//Dessiner une ligne<br />[[self window] cacheImageInRect:[self frame; //enregistre l'image
La difficulté est de les placer dans le bon ordre là ou il faut...
Une autre idée à essayer serait de définir la fenêtre comme nonretained au lieu de buffered, dans IB.
WIMP : c'est la solution ! il n'y a rien à faire dans le code.
Merci pour cette géniale idée !
Le non retained est une solution, mais ça demande de gérer soi-même le rafraichissement. Si c'est pour un usage personnel, c'est pas bien grave, mais pour une appli à diffuser, ça change tout. En non-retained, les coins de la fenêtre sont noirs, et le rafraichissement de toutes les subviews est à ta charge, et ça peut vite devenir lourd surtout si tu as des contrôles en plus dans la fenêtre. Ca peut se limiter en faisant une espèce de child window customisée non retained comportant une custom subview. Cette child window est liée à une window bufferisée qui elle comporte tout les contrôles, ensuite il n'a a plus qu'à assurer le rafraichissement de la child window dans tout les cas de figure, mais encore une fois tout ceci n'est qu'hypothèse...
Merci Eddy58.