1
votes

Coincé avec JOptionPane

Je ne suis pas sûr des meilleures pratiques avec JOptionPanes, bien que cela puisse également être un problème de logique. Je veux une zone de saisie qui demande un nom, vérifie qu'il s'agit d'une chaîne de lettres uniquement, et l'utilisateur peut annuler.

Je comprends que l'annulation d'un JOptionPane entraîne le renvoi d'un null, que j'ai implémenté au début. Le problème est que si un utilisateur entre incorrectement dans le premier volet, il ne peut pas annuler à partir du second.

EDIT: il convient de souligner que si l'utilisateur annule, je ne veux rien faire avec le nom. C'est le problème qui me force dans la boucle. La logique devrait être de vérifier l'entrée de l'utilisateur; si == 2 ne rien faire. Si autre chose, validez est un mot et utilisez-le. Bouclez si non valide. Le problème est que l'utilisateur peut annuler plus tard et que l'action d'utiliser le nom est exécutée de toute façon car il est dans la deuxième boucle, avec la valeur de 2.

J'ai actuellement:

JOptionPane optionPane1 = new JOptionPane(text, OK_OPTION, CANCEL_OPTION);
optionPane1.setWantsInput(true);
JDialog d1 = optionPane1.createDialog(null);
d1.setVisible(true);
name = optionPane1.getInputValue().toString();

if(name == null){
   gamePaused = true;
}

else{
   while(!name.matches("^[a-zA-Z]+$") || name.length() == 0){
      JOptionPane optionPane2 = new JOptionPane("Please enter a word.\nTry again.", OK_OPTION, CANCEL_OPTION);
      optionPane2.setWantsInput(true);
      JDialog d2 = optionPane2.createDialog(null);
      d2.setVisible(true);

      name = optionPane2.getInputValue().toString();
   }
   ///use name
}

Y a-t-il une meilleure façon de faire cela, afin que je puisse permettre à un utilisateur d'annuler et d'échapper à la boucle?


3 commentaires

name ne peut pas être nul, car il est obtenu en appelant optionPane1.getInputValue (). toString (); et toString () ne renverra jamais null. Votre appel au constructeur JOptionPanel est également incorrect. Lisez son javadoc: docs.oracle.com/javase/8/docs/api/javax/swing/… . Le deuxième argument ne peut pas être OK_OPTION. En général, vous devez utiliser les méthodes statiques showXxx de JOptionPane pour en afficher une.


Si votre getInputValue () renvoie null , votre code plantera puisque vous appelez toString () dessus, ce qui entraîne une situation comme null.toString () qui donne un NPE .


Consultez éventuellement cette réponse , pour une meilleure approche.


3 Réponses :


0
votes

Le problème est qu'à l'intérieur de votre boucle while , il n'y a pas d'autre vérification si l'utilisateur a appuyé sur Cancel (ce qui signifie name == null ). Une fois que l'utilisateur entre quelque chose d'invalide lors de sa première tentative, il reste à l'intérieur de la boucle while et on lui demande son nom encore et encore jusqu'à ce qu'il y ait une entrée valide, et le programme ne se soucie plus de s'il a cliqué sur Annuler. Par conséquent, vous devez ajouter avant name = optionPane2.getInputValue (). ToString (); :

if (optionPane2.getInputValue() == null) {
   gamePaused = true;
   break;
}


4 commentaires

optionPane2 ne renvoie cependant pas null. Il renverra "uninitializedValue". cette condition n'a aucun sens ici.


Cela ne me sort pas de la boucle while, cela ne fait que sortir de l'instruction if.


@Luke break est pour sortir des boucles, pas si les conditions. "Cela ne fait que sortir de la déclaration" n'a aucun sens.


C'est vrai, mais la rupture est souvent un signe de mauvaise logique. Et dans ce cas précis ne fait rien d'utile. J'apprécie cependant vos conseils.



-1
votes

Dans votre boucle while, vérifiez si annuler est sélectionné par l'utilisateur: Ajoutez ceci dans la boucle while:

if(optionPane2.getValue().toString().equals ("2")){ // 2 for close option in your case
        break;
}


2 commentaires

Cela ne me sort pas non plus de la boucle intérieure. Et même s'il le pouvait, il tenterait d'utiliser la valeur de nom, 2, pour agir avec. J'en ai besoin pour ne pas tenter d'agir à moins que le nom ne soit une chaîne.


@Luke Le nom de la chaîne n'a pas besoin d'être "2", getValue () renvoie la valeur de l'option sélectionnée, c'est-à-dire "1" pour appuyer sur Ok et "2" pour appuyer sur Annuler. Je suis juste en train de le comparer, pour savoir quel bouton est enfoncé.



1
votes

Vous pouvez remplacer tout votre code par celui-ci

do {
    name = JOptionPane.showInputDialog(null, "Enter name here : ", "title", JOptionPane.OK_CANCEL_OPTION);
} while(name != null && !name.matches("^[a-zA-Z]+$"));

if (name == null) {
    gamePaused = true;
} else {
    //Do whatever want with the name
}


1 commentaires

Je n'ai jamais envisagé de faire un moment. Réponse excellente et concise.