Utilisation d'un NSTabView à  l'affichage d'une fenêtre

UniXUniX Membre
04:51 modifié dans API AppKit #1
Salut.

Voilà  mon soucis : j'ai un windowController qui lorsqu'il est initialisé affiche une fenêtre, jusque là , rien d'anormal ... :P Cette fenêtre affiche tout un tas d'informations qu'il faut préparer avant de l'afficher.
Ma fenêtre contient une NSTabView. Le premier onglet est un onglet "d'attente" contenant un NSProgressIndicator circulaire, et le second onglet contient toutes mes données à  afficher.

Je voudrais, le temps que les données soient prêtes, afficher le 1er onglet, et lorsque tous les calculs de préparation sont finis, afficher le 2ème onglet.

J'ai essayé plusieurs choses, aucune n'a marché. Voici le code de mon windowController :
- (void)awakeFromNib<br />{<br />	[thermometre startAnimation:nil];<br />	[ongletGeneral selectTabViewItemAtIndex:0];<br />}<br /><br />- (void)windowDidLoad<br />{<br />	NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1<br />									 target:self<br />								&nbsp;  selector:@selector(initialisation:)<br />								&nbsp;  userInfo:nil<br />									repeats:NO];<br />	[timer fire];<br />}<br /><br />- (void)initialisation:(NSTimer*)theTimer<br />{<br />	// calcul de préparation des données à  afficher<br />	<br />	[ongletGeneral selectTabViewItemAtIndex:1];<br />	[thermometre stopAnimation:nil];<br />}


Le résultat n'est pas celui escompté, puisque l'onglet 0 ne s'affiche pas .... J'ai directement le 1 ....

Réponses

  • AliGatorAliGator Membre, Modérateur
    juillet 2006 modifié #2
    Ca fait un bout de temps que je n'en ai pas fait (de timers), mais ton [tt][timer fire][/tt] est loin d'être le bon plan (il a pour but de déclencher le timer immédiatement au lieu d'attendre la fin du temps !)
    A première vue il suffit de supprimer cette ligne [tt][timer fire][/tt], et ralonger un peu le temps (timeInterval) de ton timer au passage (parce que 0.1s = 100ms tu vas à  peine avoir le temps de voir ton 1er onglet, donc pour le test met plutôt 1 ou 2s)

    Soit tu revois ton utilisation des timers, soit (car j'imagine qu'il n'est là  que pour les tests en attendant de réellement charger tes données ?) tu mets un bouton dans ton premier onglet que tu relies à  une action qui va t'afficher le 2e onglet. Le temps de tester, quoi, en attendant que tu implémentes réellement le chargement des données bouffeur de temps.
  • BruBru Membre
    04:51 modifié #3
    T'as raison Ali,
    l'utilisation des méthodes sheduled... font que le NSTimer n'a pas besoin de fire pour se déclencher.

    D'autre part, le délai de 0.1 représente 1/10 de seconde d'attente avant déclenchement de la méthode initialisation: font que l'intervalle de temps est extrêmement court pour l'affichage de l'onglet 0 (même pour les spécialistes en lecture rapide).

    .
  • UniXUniX Membre
    04:51 modifié #4
    Ben en fait, j'avais mis le fire car sinon mon timer ne partait pas ...

    Je viens de refaire l'essai, j'ai enlevé le [timer fire], et j'ai mis 1 seconde de délai pour le timer.
    J'ai bien la première page de mon onglet qui s'affiche, mais je reste bloqué là  .... La méthode initialisation ne part pas et donc, la seconde page de l'onglet ne s'affiche pas ...
  • Eddy58Eddy58 Membre
    04:51 modifié #5
    Je ne vois pas pourquoi ton timer ne fonctionne pas (la méthode windowDidLoad est-elle bien appelée ?), mais dans ce genre de cas, un performSelector:withObject:afterDelay: est bien suffisant. :)
    [tt]
    -(void)windowDidLoad
    {
    [self performSelector:@selector(initialisation) withObject:nil afterDelay:1];
    }
    [/tt]
  • UniXUniX Membre
    04:51 modifié #6
    Bon, en fait je sais pourquoi le timer ne démarrais pas .....

    Lors de la création de l'instance du windowController, je rend la fenêtre créée modale avec [NSApp runModalForWindow:[informations window]]. Et c'est ça qui bloque.
    Je me suis apperçu que ma méthode initialisation partais lorsque je faisais le [NSApp stopModal].

    Si je vire le modal, tout marche impec. Mais alors, comment combiner le tout ?
  • AliGatorAliGator Membre, Modérateur
    04:51 modifié #7
    Et avec la méthode proposée par Eddy, le fait d'être dans une modal loop est tout aussi bloquant ?
  • UniXUniX Membre
    04:51 modifié #8
    Oui, c'est pareil ....
  • BruBru Membre
    04:51 modifié #9
    Les fenêtres modales créent et utilisent une autre runLoop.
    La runLoop précédente est donc suspendue.

    Comme les NSTimer sont déposés dans cette précédente runLoop, alors ils ne se déclencheront pas avant que la runLoop de la fenêtre modale ne soit terminée.

    De manière générale, toute opération gourmande en temps d'exécution doit se faire dans un thread séparé avec synchro avec le thread principal. Cela permet :
    • 1. de ne pas bloquer le thread principal (celui lié à  l'affichage)
    • 2. de laisser l'application capable de répondre à  des messages "extérieurs" pendant qu'elle mouline.


    Pour l'utilisation des NSThread et leur synchronisation, demande à  nos spécailistes ici (Chacha, Ali et Eddy pour ne citer que les meilleurs).

    .
  • AliGatorAliGator Membre, Modérateur
    juillet 2006 modifié #10
    Juste une question quand même UniX pour être sûr :
    Ton Timer là , c'est juste temporaire pour tester le passage automatique de ton onglet 1 à  ton onglet 2 ?
    A terme, tu déclencheras le passage de l'onglet "Chargement..." à  celui d'affichage des données par un autre moyen, hein ?
    Par exemple par un appel à  une méthode (qui changera justement d'onglet, donc) au moment où les données auront fini d'être chargées ?

    Ou tu comptais vraiment le faire à  la louche en mettant un temps grosso-modo et en te disant "bah au bout de N secondes ça devrait avoir fini de charger" ??

    Si c'est bien ce que j'espère, à  savoir que c'est temporaire et qu'à  terme tu changeras d'onglet par un appel à  une méthode, alors le problème est tout de suite résolu. D'autant que comme le dis Bru tu devras certainement déporter le chargement de tes données dans un NSThread séparé (puisque ce chargement de données risque d'être un poil long et qu'il ne faut pas qu'il soit bloquant pour l'affichage)... NSThread qui pourra alors faire appel à  un message genre [tt]didFinishLoading:[/tt] dès qu'il aura fini ;)


    PS : Ne peut-on pas enregistrer un NSTimer dans une autre runLoop que la runLoop principale... justement dans la modal Loop ? Enfin bon ça change pas le problème conceptuel
  • UniXUniX Membre
    04:51 modifié #11
    Non, en fait j'avais mis un Timer pour dissocier les calculs et l'affichage. Le NSTimer faisant une sorte de tâche parallèle, je voulais afficher l'onglet d'attente, lancer les calculs via le timer qui, une fois les calculs finis, m'affichait l'onglet d'affichage.

    Je vais aller de ce pas jeter un oeil sur les NSThread que je n'ai jamais utilisé encore.
Connectez-vous ou Inscrivez-vous pour répondre.