9
votes

Où est le fil d'expédition de l'événement?

Je lis que tout le code qui construit des composants et des poignées de balançoires Les événements doivent être exécutés par le fil d'expédition de l'événement. Je comprends comment cela est accompli en utilisant la méthode oscillabilité.invokelater () . Considérez le code suivant où l'initialisation de l'interface graphique est effectuée dans la méthode principale xxx

Comment ce code fonctionne parfaitement? Nous construisons jframe et appelant une foule d'autres méthodes dans le fil principal. Je ne comprends pas où exactement l'EDT vient en photo ici (quel code est-il exécutant?). Le constructeur de la classe gridbaglayouttester est également appelé à partir de la méthode principale qui signifie que l'EDT ne fonctionne pas.

en courte

  1. Quand est-ce que l'EDT commence? (Le JVM démarre-t-il l'EDT avec la méthode principale si l'EDT est démarré lors de l'exécution de ce code?)
  2. Le code du gestionnaire d'événements pour le bouton fonctionne-t-il sur l'EDT?

0 commentaires

4 Réponses :


1
votes

1) Je ne sais pas si dans Nouveau Jframe ou dans SETVISIBLE Mais il initialise à la demande et c'est la fin de la méthode principale (sur le processus principal Le fil) ne termine pas le processus. L'EDT a été lancé et est dans une boucle bloquée en attente de l'événement suivant.

2) définitivement. Cette boucle reçoit du système d'exploitation, trouvez le JButton et lui dit que l'événement a été licencié. Le bouton appelle ensuite les auditeurs. Tout ce qui arrive dans l'EDT.

Vous pouvez consulter le code de swing que vous appelez lorsque vous souhaitez tuer le processus (ou fermer la fenêtre principale) pour la recherche de l'endroit où l'EDT est terminé ... qui peut vous donner un indice (je le ferai plus tard! :)


0 commentaires

3
votes

Le fil d'expédition de l'événement, comme son nom l'implique, est appelé par balançoire à chaque fois qu'un événement doit être traité.

Dans l'exemple que vous avez donné, le bouton "Test" appelle automatiquement la méthode Actionperformée lorsqu'un événement d'action doit être traité. Donc, le contenu de votre méthode activeforme sera invoqué par le fil d'expédition d'événement.

Pour répondre à vos deux questions finales:

  • L'EDT est démarré automatiquement lorsque le cadre de balançoire charge. Vous n'avez pas à vous soucier de démarrer ce fil, le JRE gère cette tâche pour vous.
  • Le code du gestionnaire d'événements est exécuté par l'EDT. Tous les événements que votre interface pivotante génère sont regroupés et l'EDT est responsable de les exécuter.

0 commentaires

12
votes

Le code fonctionne parfaitement car vous construisez le cadre dans le fil principal, avant que l'EDT ait l'occasion d'interagir avec elle. Techniquement, vous ne devriez pas le faire de jamais, mais techniquement, vous pouvez dans cette circonstance spécifique, car vous ne pouvez pas interagir avec le jframe avant de devenir visible.

Le point principal à savoir est que les composants swing ne sont pas en sécurité. Cela signifie qu'ils ne peuvent pas être modifiés de plus d'un fil en même temps. Ceci est résolu en veillant à ce que toutes les modifications proviennent de l'EDT. P>

L'EDT est un fil dédié à l'interaction de l'utilisateur. Tous les événements générés à partir de l'utilisateur sont toujours exécutés sur l'EDT. Toute mise à jour d'interface utilisateur exécutée sur l'EDT. Par exemple, lorsque vous appelez composant.Repaint () code>, vous pouvez appeler cela à partir de n'importe quel fil. Cela définit simplement un drapeau pour marquer le composant comme nécessitant une peinture, et l'EDT le fait sur son prochain cycle. P>

L'EDT est démarré automatiquement et est liée de près dans la mise en œuvre du système. Il est bien géré dans la JVM. En règle générale, elle est corrélée à un seul fil dans le système de fenêtrage qui gère l'interaction utilisateur. Bien sûr, cela est assez dépendant de la mise en œuvre. La bonne chose est que vous n'avez pas à vous soucier de cela. Il vous suffit de savoir - si vous interagissez avec des composants de balançoire, faites-le sur l'EDT. P>

De même, il y a une autre chose qui est importante. Si vous allez effectuer un traitement de la durée de longue durée ou un blocage d'une ressource externe, vous allez le faire en réponse à un événement généré par l'utilisateur, vous devez planifier cela pour fonctionner dans son propre thread de l'EDT. Si vous ne le faites pas, vous ferez blocer l'interface utilisateur pendant qu'il attend que le traitement de la durée de longue durée est exécuté. D'excellents exemples sont en cours de chargement à partir de fichiers, de la lecture d'une base de données ou d'interagir avec le réseau. Vous pouvez tester pour voir si vous êtes sur l'EDT (utile pour créer des méthodes neutres pouvant être appelées à partir de n'importe quel thread) avec le oscillabilité.isEventDispatThread () code> méthode. P>

voici Deux extraits de code que j'utilise assez fréquemment lors de l'écriture de la programmation de la balançoire avec l'EDT: P>

void executeOffEDT() {
  if (SwingUtilities.isEventDispatchThread()) {
    Runnable r = new Runnable() {
      @Override
      public void run() {
        OutsideClass.this.executeOffEDTInternal();
      }
    };
    new Thread(r).start();
  } else {
    this.executeOffEDTInternal();
  }
}

void executeOnEDT() {
  if (SwingUtilities.isEventDispatchThread()) {
    this.executeOnEDTInternal();
  } else {
    Runnable r = new Runnable() {
      @Override
      public void run() {
        OutsideClass.this.executeOnEDTInternal();
      }
    };
    SwingUtilities.invokeLater(r);
  }
}


6 commentaires

En ce qui concerne le composant.Repaint (), je doute que cela ne fait que "définir un drapeau", il file en fait un événement de peinture (qui sera ensuite traité par l'EDT).


Le motif est le même. Vous n'avez pas besoin de connaître les internes de la manière dont cela est manipulé afin d'utiliser l'EDT avec succès.


donc l'appel de cadre.setsvision () est exécuté sur l'EDT?


Non. Dans votre exemple, la méthode principale () est exécutée sur le fil principal. La seule ligne de code exécutée sur l'EDT est dans la méthode Actionperalisée. La norme que j'ai vue est de créer une sorte de méthode initializeuserInterface () et de les envelopper dans une invoquation à l'aide du fil principal. Ensuite, vous déplacez tout le contenu de la méthode principale. C'est la bonne façon de le gérer.


@ERICK SE FULLIMICIALY Les composants balançoires peuvent en effet être construits et rendus à partir du thread principal, même s'il est préférable de déplacer ce code sur l'EDT.


Oui. Si vous essayez de le faire avant qu'il ne soit visible à l'écran, il ne se cassera pas parce que personne ne peut interagir avec elle pendant que vous le configurez. Si vous essayez de le faire après sa visibilité à l'écran, vous risquez de lancer des exceptions de concurrence.



0
votes

Le thread EDT est démarré après que vous appeliez d'abord SETVisible (true); s'il n'est pas démarré déjà, OFC. Ou si vous appelez oscillabilité.invokeandwait () ou oscillabilité.invokelater () méthodes.

voir http://www.leeppoint.net /Javabasics/gui/GuI-CommENTration /Guicom-Main-thread.html


0 commentaires