8
votes

Forcer Flex pour mettre à jour l'écran?

Cela peut être un peu une question débutante, mais je ne peux pas pour la vie de moi la figure.

J'utilise Flex pour développer une interface graphique pour un grand projet, plus particulièrement une barre d'état le long du bas. Dans ma classe de barre d'état est une barre de progression, que d'autres classes travaillent peuvent dire à la mise à jour (modifier la barre d'achèvement et étiquette) au fur et à mesure de leur progression. Le problème que je rencontre est que Flex ne mettra pas à jour ce qui est affiché à l'écran jusqu'à ce qu'il soit trop tard, par exemple

Progressbar initialisé, 0% fait
Certains classes définissent la barre de progression pour être 12% faite
une certaine classe fait des tâches
Certains classes définissent la barre de progression pour être 56% faite

Ce qui se passe est que 12% fait ne s'affiche jamais, il se bloque à 0% pendant le travail, puis saute jusqu'à 56%. J'ai essayé de comprendre le cycle de vie d'un composant Flex (invalidation et validation), et je pense que je le comprends et je l'applique correctement, mais cela ne fonctionne pas du tout. J'ai besoin de dire flex pour redessiner ma barre d'état (ou au moins la barre de progression dans) après certains classes la définit à 12%, mais avant certains classes commence à faire son travail . Comment puis-je faire cela?


1 commentaires

Ce problème devrait vraiment être considéré comme permettant à flex pour mettre à jour l'écran. Comme indiqué ci-dessous, Flash est un modèle d'exécution à une seule-filetage pour votre code. Ainsi, vous devez calculer votre travail permettant au joueur de rafraîchir l'affichage entre les morceaux. CallLater () ou utiliser des minuteries pour contrôler les morceaux Les mécanismes de base sont disponibles. N'oubliez pas que si vous faites pas le faire, le navigateur tient probablement le temps de flash après 45 secondes (défaut FF)


6 Réponses :


2
votes

Essayez d'appeler InvalidateDisplayList () après chaque modification de votre barre de progression. Quelque chose comme: xxx

flex a un cycle d'invalidation qui évite l'écran redessinant chaque fois que des modifications de la propriété. Par exemple, si la valeur d'une propriété change 3 fois dans une seule image, elle ne fera que le dernier ensemble de valeur. Vous pouvez forcer un composant à redéresser en appelant InvidateDisplayList (), ce qui signifie que UpdateDisplayList sera exécuté immédiatement au lieu d'attendre la trame suivante.


2 commentaires

En réalité, cela n'invoque pas de mise à jourInplaylist () "immédiatement", mais il l'invoquera à la mise à jour / cadre à l'écran suivant. Si cela le faisait immédiatement, il serait en quelque sorte défaire le point du modèle d'invalidation / validation.


Mon mauvais, tu es absolument juste. Au lieu d'appeler InvalidateDisplayList (), vous devez appeler directement UpdateDisplayList ()



2
votes

ActionScript dans Flash Player, comme JavaScript dans le navigateur, est pseudo-multithreaded. C'est-à-dire qu'ils sont uniformes, mais ils ont plusieurs piles d'exécution. Cela signifie que vous ne pouvez pas «dormir» dans un fil particulier, mais vous pouvez apparaître une nouvelle pile d'exécution qui est différée jusqu'à une heure ultérieure. La manière flexible de faire est la fonction "CallLater". Vous pouvez également utiliser les fonctions Settimeout / Seinterval. Ou vous pouvez utiliser un objet de minuterie intégré au lecteur Flash. Ou même "Enter_frame" Evénement auditeur. Tous ces éléments vous permettront essentiellement de faire ce dont vous avez besoin, si je corrige la cause de vos problèmes.

On dirait que vous avez un "fil" faisant la majeure partie de votre travail, ne vous arrêtez jamais pour permettre à d'autres piles d'exécution (threads *).

Le problème pourrait être ce que dit Pez, mais si cela n'aide pas, vous voudrez peut-être essayer des appels différés pour les cours de travailleurs. Donc, votre processus pourrait ressembler à ceci maintenant:

  1. Progrès initialisés.
  2. Faites du travail.
  3. Mise à jour de la barre de progression à 12. (Invalider la liste d'affichage)
  4. Settimeout (Domorework, 100);
  5. Mise à jour de la barre de progression à 52.

    (Si votre travailleur est un UIComponent, vous pouvez utiliser uicomp.Calllater (...), sinon, vous devez utiliser Settimeout / TIMERS / ENTER_FRAME pour les classes PURE AS3).


0 commentaires

9
votes

Comme mentionné dans d'autres réponses, le lecteur Flash est unique, si vous ne rompez pas votre travail dans des morceaux distincts pouvant être exécutés dans des "cadres" distincts, vous allez voir des sauts et des protégés dans l'interface utilisateur , qui est efficacement ce que vous voyez.

Si vous devez vraiment voir que 12% de message, il ne suffit pas d'invalider la liste d'affichage, car la liste d'affichage n'a aucune chance de mettre à jour après la fin du travail de 56%, vous devez interrompre explicitement le naturel. Cycle d'événement avec un appel à validateNow () Une fois votre message défini.

Cela n'est cependant pas le meilleur moyen de faire des choses si la performance est préoccupante. Vous pouvez obtenir avec une utilisation judiciaire de CallLater () pour planifier chaque morceau de travail à son tour, car cela permettra au joueur de compléter potentiellement un cycle de trame (et de mettre à jour la liste d'affichage) avant de tenter la prochaine pas dans votre processus.


3 commentaires

Je ne peux toujours pas l'obtenir, j'appelle InvalidatedisplayList () suivi immédiatement par Validatenow () et il ne semble pas mettre à jour. Ma classe de barre d'état ainsi que la barre de progression et la progressionBarskin sont en cours d'invalidation, puis validées, cela va bien cependant le thrake () pour réellement redessiner la partie remplie de la barre de progression, mais elle ne met toujours pas à jour sur l'écran.


Avez-vous essayé CallLater, Settimeout ou similaire, comme je l'ai suggéré? On dirait que votre traitement bloque le rendu de mise à jour de l'écran. Vous devez faire une pause et laissez-le respirer.


Aha! Parlez de bizarre, je peux le faire mettre à jour lorsque je veux utiliser Settimeout, tant que le temps d'exécuter le reste de la fonction après que le Settimeout (Dowork, X) prend moins que X. En d'autres termes, je dois laisser Flash aller oisif (pour plus de 25ms). Cela se casse cependant si je mets des points d'arrêt au mauvais endroit ou si j'essaie de passer à travers le code.



3
votes

Glenn,

Ce n'est pas du tout à quel point le threading in Flex fonctionne quoi que ce soit. Comme beaucoup d'UIS, il a une pompe de message sur le fil principal de l'interface utilisateur (ils le font dans des cadres). Lorsque vous appelez CallLater () Strard> Il place le pointeur de fonction transmis à la fin de la file d'attente de la pompe de message (sur la trame suivante) et retourne immédiatement. La fonction est alors appelée lorsque la pompe de message a fini de traiter tous les messages précédents (comme des clics de souris). P>

Le problème est que le changement de propriété entraîne des événements de l'interface utilisateur à déclencher, ils placent ensuite leur propre des messages sur la pompe qui vient maintenant après l'appel de votre méthode que vous avez placée à partir de CallLater () forte>. p>

Flex a plusieurs threads, mais ils sont là pour les raisons de Adobe et sont donc pas accessible par l'utilisateur. Je ne sais pas s'il existe un moyen de garantir qu'une mise à jour de l'interface utilisateur se produira à un point spécifique, mais une option consiste à appeler CallLater forte> plusieurs fois jusqu'à ce que l'opération se produise. Commencez avec un petit nombre et augmentez jusqu'à ce que le nombre d'itérations produit le résultat souhaité. Exemple: P>

// Change this to a number that works... it will probably be over 1, depending on what you're doing.
private const TOTAL_CALL_COUNT:int = 5;

private var _timesCalled:int = 0;

//----------------------------------------------------------------
private function set Progress( progress:int ):void
{
    progressBar.value = progress;
    DoNextFunction();
}

//----------------------------------------------------------------
private function DoNextFunction():void
{
    if( _timesCalled >= TOTAL_CALL_COUNT )
    {
        _timesCalled = 0;
        Function();
    }
    else
    {
        _timesCalled++;
        callLater( DoNextFunction );
    }
}


2 commentaires

Vous êtes mal compris ma réponse. Je parlais d'AS3 / Flash surtout, pas de flex. "CallLater" est une implémentation flexible en plus de cela. Il utilise simplement des événements comme Enter_frame à travailler en arrière-plan.


Suspension de CallLater pour SettimeOut le ferait fonctionner dans AS3.



0
votes

J'utilise Flash Builder 4.6 et j'ai également un problème pour l'affichage de ma barre de progression. J'ouvre une nouvelle fenêtre où je démarre une nouvelle classe MultiLoader (39 Mo de contenu). La nouvelle fenêtre est ouverte en arrière-plan et la fenêtre principale affiche une barre de progression jusqu'à ce que la classe MultiLoader ait terminé son travail. Cependant, la fenêtre d'ouverture bloque l'animation de ma fenêtre principale. Je sais que ce n'est pas la classe multiloader parce que je l'ai vu courir correctement.

Mais je vais essayer de trouver de nouvelles façons de le faire.

L'objectif principal de mon message est la complexité Adobe a construit autour de Flash. Lorsque vous recherchez des ressources pour votre propre application ou vos réponses à vos questions, c'est une vraie douleur à trouver le bon Ressource. Il existe un mélange total (au côté Adobe et au côté de l'utilisateur) entre As3, Flex, Flash Cs, Builder Flash, Air, ... Si vous essayez de développer dans AS3, vous constaterez que certains exemples ne fonctionneront pas pour vous parce que cela n'est pas implémenté dans votre SDK. Vous avez de plus en plus de forums vous donnant la "meilleure pratique" ou des réponses ironiques basées sur des expériences sur différentes plateforme de développement.

Par exemple, juste ci-dessus, je vois progressable.value = valeur; Avec mon expérience, je peux dire que dans Flash Builder 4.6, cette propriété est en lecture seule. Mais cela pourrait être une classe personnalisée faite par l'utilisateur mais qui peut le dire.


0 commentaires

1
votes

Parfois, c'est nécessaire à zéro avant d'assigner une autre valeur. progressable.setProgress (0, progressable.maximimum); ProgressBar.SetProgress (NewValue, ProgressBar.Maximum);


0 commentaires