Utilisation d'un NSTabView à l'affichage d'une fenêtre
UniX
Membre
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 :
Le résultat n'est pas celui escompté, puisque l'onglet 0 ne s'affiche pas .... J'ai directement le 1 ....
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 /> selector:@selector(initialisation:)<br /> 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 ....
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
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.
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).
.
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 ...
[tt]
-(void)windowDidLoad
{
[self performSelector:@selector(initialisation) withObject:nil afterDelay:1];
}
[/tt]
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 ?
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 :
Pour l'utilisation des NSThread et leur synchronisation, demande à nos spécailistes ici (Chacha, Ali et Eddy pour ne citer que les meilleurs).
.
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
Je vais aller de ce pas jeter un oeil sur les NSThread que je n'ai jamais utilisé encore.