2017-10-01 6 views
0

Je suis intrigué par le bug qui apparaît dans le code que j'ai écrit. Cela fonctionne parfaitement en C# mais de toute façon cela ne fonctionne pas en Java. Je ne suis pas sûr si cela a quelque chose à voir avec la deuxième fois que je l'ai défini. Je l'ai vérifié avec mon autre classe qui passe les boutons dans cette classe et je ne trouve rien qui puisse affecter cette classe. Une autre chose à noter est que tous les composants Swing ne sont pas NULL lorsqu'ils sont passés dans cette classe.Les composants swing de Java ne sont pas mis à jour correctement et enum est sélectionné deux fois par fonction

Mon principal problème est que tous les boutons ne se mettent pas à jour après le réglage du texte pour le deuxième temps.

public class StoryManager extends Text{ 
    // this is the body of the story 
    private JTextPane textPane; 
    // the choices that the user can make 
    private JButton btnChoice1; 
    // this would determine which ending the user will get 
    private short ending = 0; 

/** 
* checkpoint for each part of the story 
* */ 
public enum Part{ 
    START, A_JOKE, B_BASE 
} 
// the part that the user is currently in 
Part userPart; 

/** 
* This runs the story. 
* */ 
public void PlayStory() { 
    printText(); 
    processDecision(); 
} 
/** 
* This attaches the buttons and the textPane to their corresponding variables in the class. 
* */ 
public StoryManager(WindowHandler windowHandler) { 
    // pane 
    textPane = windowHandler.getTextPane(); 
    // buttons 
    btnChoice1 = windowHandler.getBtnChoice1(); 
    // set the user to start the story from the beginning 
    userPart = Part.START; 
} 

@Override 
public void printText() { 
    switch(userPart) { 
    case START: 
     System.out.println("Start event started"); 
     textPane.setText("some text" 
       + "[1] option 1\n"); 
     break; 
    case A_JOKE: 
     System.out.println("A_JOKE event started"); 
     textPane.setText("another text 1" 
       + "[1] option 1\n"); 
     break; 
    case B_BASE: 
     System.out.println("B_BASE event started"); 
     textPane.setText("another text 2" 
       + "[1] option 1\n"); 

     break; 
    default: 
    } 
    textPane.setCaretPosition(0); 
    textPane.repaint(); 
} 
/** 
* Enables all the buttons. 
* */ 
private void EnableAllButtons() { 
    if(!btnChoice1.isEnabled()) { 
     btnChoice1.setEnabled(true); 
     btnChoice1.setOpaque(true); 
     btnChoice1.setContentAreaFilled(true); 
     btnChoice1.setBorderPainted(true); 
    } 
    btnChoice1.repaint(); 
    //System.out.println("Button1: "+btnChoice1.isEnabled()); 
} 
/** 
* Temporarily disables the other buttons and runs the PlayStory() again to continue the story. 
* 
* @param button The button that is clicked. 
* */ 
private void SetDecisionText(JButton button) { 
    button.setText("Next"); 
    btnChoice1.revalidate(); 
    PlayStory(); 
} 
/** 
* Sets the action of the button per part. 
* */ 
@Override 
public void processDecision() { 
    switch(userPart) { 
    case START: 
     btnChoice1.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       ending -= 10; 
       userPart = Part.A_JOKE; 
       SetDecisionText(btnChoice1); 
      } 
     }); 
     break; 
    case A_JOKE: 
     btnChoice1.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       btnChoice1.setText("Choice 1"); 
       //btnChoice1.revalidate(); <- tried this but it isn't working 
       GoToBase(); 
      } 
     }); 
     break; 
    case B_BASE: 
     System.out.println("Updated with B_BASE"); 
     btnChoice1.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       ending -= 10; 
       userPart = Part.B_ARGUE; 
       SetDecisionText(btnChoice1); 
      } 
     }); 
    } 

} 
private void GoToBase() { 
    EnableAllButtons(); 
    switch(userPart) { 
    case A_JOKE: 
     userPart = Part.B_BASE; 
     System.out.println("GotoBase: " + userPart); 
     break; 
    default: 
     System.out.println("Error"); 
    } 
    PlayStory(); 
} 

} 

Je vais partager la sortie de mon programme ici. J'ai sélectionné le premier bouton deux fois alors cela arrive. Lorsque je l'appuie à nouveau, userPart devient nulle ou quelque chose.

// pressed play 
Start event started 

// click 1st button 
A_JOKE event started 

// click 1st button again 
GotoBase: B_BASE 
B_BASE event started 
Updated with B_BASE 
A_JOKE event started 

// click 1st button for the third time 
GotoBase: B_BASE 
B_BASE event started 
Updated with B_BASE 
Error 
A_JOKE event started 
+0

* "Liste des problèmes:" * Quelle est votre ** seule ** question pour ce fil de discussion? Ceci est un site Q & A, pas un service d'assistance. Les questions séparées doivent être montrées sur des fils séparés, chacun avec un MCVE spécifique à la question. –

+1

Voir modifier pour répondre par exemple à ce que je veux dire en supprimant les écouteurs. Mais encore une fois pour mon argent, je travaillerais à refactoriser le tout si j'étais à votre place. Efforcez-vous pour un modèle (partie logique) qui fonctionnerait avec Swing, JavaFX ou même un programme de console si désiré. –

Répondre

1

Vous semblez ajouter ActionListeners à vos boutons dans la partie logique de votre code, et vous faites cela signifie que les boutons auront ActionListeners ajoutés pour les plusieurs fois, chaque fois que la méthode processDecision() est appelée, ce qui entraîne par la suite en boutons avec plusieurs écouteurs ajoutés à eux, ce qui n'est pas ce que vous voulez. Les écouteurs doivent être ajoutés une fois, lors de la création du composant.

Si vous voulez échanger des ActionListeners, veillez à supprimer les anciens écouteurs lors du remplacement par les nouveaux.

Il y a probablement d'autres problèmes logiques dans votre code, mais c'est la limite de ce que je peux suggérer jusqu'à ce que vous soyez en mesure de fournir un Minimal, Complete, and Verifiable Example Program valide pour nous. C'est là que vous condensez votre code dans le plus petit bit qui compile et s'exécute, n'a aucune dépendance extérieure (comme un lien vers une base de données ou des images), n'a pas de code supplémentaire qui ne correspond pas à votre problème, mais démontre votre problème .

Un gros problème que je vois est que votre code a un très haut couplage et une faible cohésion, ce qui rend le code très fragile, et le code difficile à déboguer. Envisagez de refactoriser, en séparant votre modèle (la partie logique de votre programme) de votre vue (la partie GUI) et en séparant les données du code, en vous débarrassant du texte d'affichage codé en dur et en le plaçant dans un référentiel de données, que ce soit un fichier texte, une base de données ou tout ce qui fonctionne le mieux.

exemple de suppression d'écouteurs:

case A_JOKE: 
    for (ActionListener l : btnChoice1.getActionListeners()) { 
     btnChoice1.removeActionListener(l); 
    } 
    btnChoice1.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      btnChoice1.setText("Choice 1"); 
      // btnChoice1.revalidate(); <- tried this but it isn't 
      // working 
      GoToBase(); 
     } 
    }); 
    break; 

En aparté, vous voulez apprendre et à utiliser Java naming conventions qui sont différentes de celles utilisées pour C#. Les noms de variable doivent tous commencer par une lettre plus basse, tandis que les noms de classe doivent être précédés d'une lettre majuscule. Apprendre cela et suivre cela nous permettra de mieux comprendre votre code, et vous permettra de mieux comprendre le code des autres.

+0

Autres problèmes - vous mélangez du code avec des données, et cela vous mènera à de graves maux de tête plus tard. –