Question

Je pose beaucoup de questions au sujet d'un projet, je travaille récemment. Voici le scénario que je suis et toute aide ou d'un point dans la bonne direction aiderait beaucoup ...

Ceci est un programme de réseau construit avec un serveur et plusieurs clients. Chaque client dispose d'une interface utilisateur qui doit agir en fonction de commandes envoyées à partir du serveur. Chaque client est enveloppé dans une classe appelée Player. Cette Player a une interface utilisateur graphique (étend JFrame) et une méthode principale, et le serveur a une méthode principale uniquement (pas de GUI). Dans un premier temps, cette classe a été créée dans le thread principal comme ceci:

EventQueue.invokeLater(new Runnable()
{
    public void run()
    {
        new Player().setVisible(true);
    }
 });

Ce fonctionnait bien, jusqu'à ce que je compris que toute la classe Player exécutait maintenant dans l'EDT. Alors, quand j'attends des commandes à partir du serveur les verrous entiers GUI jusqu'à cette commande est envoyée et les actions appropriées sont exécutées. Comme vous pouvez l'imaginer, c'est un horrible dessein et se sont révélés être une vraie douleur d'un environnement de codage lorsque chaque fois que vous voulez vérifier quelque chose que vous devez trouver un travail fou autour de sorte que l'interface graphique reste intacte.

De toute évidence, je dois vérifier les commandes à partir du serveur dans un thread séparé et exécuter les composants de l'interface graphique du EDT. Ma deuxième mise en œuvre avait deux classes - une pour l'interface graphique et un pour le Player. L'idée était que la Player avait une variable qui a tenu l'interface graphique pour que je puisse accéder à l'interface de la classe Player, quelque chose comme ceci:

class Player
{
    public GUI gui;

    ...

    // And then start this gui inside of the EDT.
    EventQueue.invokeLater(new Runnable()
    {
         public void run()
         {
              this.gui = new GUI().setVisible(true);
         }
    }

Cela ne fonctionne pas non plus, parce que this intérieur du nouvel objet Runnable fait référence à l'objet Runnable, pas le Player.

Comment puis-je communiquer entre la classe Player dans un thread et la classe GUI correspondante dans le fil EDT?

Était-ce utile?

Autres conseils

Pour gérer votre problème avec le pointeur de this, vous devez écrire:

class Player
{
    public GUI gui;

    ...

    // And then start this gui inside of the EDT.
    EventQueue.invokeLater(new Runnable()
    {
         public void run()
         {
              Playser.this.gui = new GUI().setVisible(true);
         }
    }
}

Boris Pavlović obtient le droit de syntaxe (en fait, vous pouvez simplement supprimer le this.), mais le code n'a pas de sens. Le champ gui est initialisée quelque temps après l'événement Runnable est mis en attente, il est dangereux pour le fil de joueur à utiliser.

Vous pouvez construire Player sur l'EDT (mais pas les opérations de réseau hors HAE). Ou enregistrez-vous l'interface graphique en tant qu'auditeur (observateur) du Player. invokeAndWait fonctionnerait, mais est dangereuse car elle conduit souvent à l'impasse difficile à debug occasionnel.

Vous pouvez essayer ceci:

joueur de classe {     GUI publique IUG;

...

// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
     public void run()
     {
          Player.this.gui = new GUI().setVisible(true);
     }
}

« jusqu'à ce que je compris que l'ensemble de la classe du joueur exécutait maintenant dans le EDT »

Le constructeur se produit sur l'EDT mais les méthodes dites de cette classe pourrait ne pas être.

Vous devez construire l'interface graphique du lecteur comme vous le souhaitez à l'origine.

 EventQueue.invokeLater(new Runnable() 
 {
    public void run()
    {
        new Player().setVisible(true);
    }
 });

Mais joueur peut lancer un thread séparé dans le constructeur (personnellement, je partage un lien entre les joueurs).

Bien sûr, devraient utiliser invokeLater les méthodes de rappel à partir du serveur () lors de la modification des composants visibles.

Au lieu d'utiliser une classe interne anonyme, pourquoi ne pas simplement déclarer une classe les outils Runnable et un constructeur qui prend une instance GUI comme argument?

En outre, si votre classe GUI est pas sûre, pensez à utiliser une file d'attente de messages pour communiquer entre le fil DETC principal.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top