2013-01-07 2 views
2

J'ai donc créé une application Java qui utilise un JSpinner et un ChangeEventListener pour exécuter du code lorsque certaines valeurs sont atteintes. Lorsque ces valeurs sont atteintes, un JOptionPane apparaît. Mais alors le JSpinner continue de tourner. Donc, si le JSpinner permettait les valeurs 1-50 et que j'avais augmenté le JSpinner de 20 à 21, il passait à 50 alors que le JOptionPane était ouvert.JSpinner continue de tourner pendant que JOptionPane est affiché sur ChangeListener

La chose étrange est, c'était un bogue connu dans Java 1.4.2, mais était censé être corrigé dans 5.0 (Bug ID: 4840869). Je cours Java 6u37. En fait, le code source fourni dans le bug (montré ci-dessous) a exactement le même effet pour moi que pour l'original du bug. Cela n'a certainement pas été réparé pour moi. La seule chose à laquelle je peux penser à propos de ce que cela pourrait être, c'est que je cours Mac OS 10.7.5 et peut-être que le correctif n'a pas été intégré à ma version d'une manière ou d'une autre. Y at-il quelque chose que je peux faire pour empêcher ce comportement de se produire?

code source démontrant ce (à l'origine du rapport de bogue):

import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JSpinner; 
import javax.swing.SpinnerNumberModel; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class SpinnerFrame extends JFrame implements ChangeListener { 

    private JSpinner spinner; 

    private boolean changing; 

    private SpinnerFrame() { 
     super(); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     getContentPane().add(getSpinner()); 
     setSize(80,60); 
     setLocation(200, 300); 
     setVisible(true); 
     changing = false; 
    } 

    private JSpinner getSpinner() { 
     if (spinner == null) { 
      spinner = new JSpinner(); 
      spinner.setModel(new SpinnerNumberModel(10, 1, 50, 1)); 
      spinner.addChangeListener(this); 
     } 
     return spinner; 
    } 

    public void stateChanged(ChangeEvent e) { 
     JSpinner spinner = (JSpinner) e.getSource(); 
     int value = ((Integer) spinner.getValue()).intValue(); 
     System.out.println("Changed to " + value); 
     if (changing) { 
      return; 
     } 
     changing = true; 
     if (value > 20) { 
      JOptionPane.showMessageDialog(this, "20 exceeded"); 
      //While this is up, the JSpinner continues to 50 
     } 
     changing = false; 
    } 

    public static void main(String[] args) { 
     new SpinnerFrame(); 
    } 
} 

Répondre

2

Je pense que si vous affichez la fenêtre de message dans un EventQueue#invokeLater() il ne devrait pas avoir ce problème. Si vous voulez annuler l'essorage à 21 après l'affichage, réinitialisez la valeur à 20 après.

+0

Cela a finalement résolu mon problème. En fait, j'ai déjà une classe Factory pour les options de dialogue afin de simplifier les paramètres du code, donc c'est très facile pour moi de l'implémenter. Merci beaucoup! – Thunderforge

+0

J'ai depuis découvert que cela fonctionne pour un simple clic sur la flèche vers le haut, mais si vous maintenez la flèche vers le haut, les boîtes de dialogue se répètent toujours. Des idées? – Thunderforge

+0

Vérifie si la boîte de dialogue est en train de s'afficher et ne la résout pas si c'est le cas. –

2

je peux reproduire un effet similaire en utilisant soit JDK 5 et 6 sur une version antérieure de Mac OS X. L'effet se produit lors de l'utilisation du souris, mais pas le clavier.

  1. Alors que la souris reste enfoncé sur flèche vers le haut de la fileuse, la boîte de dialogue apparaît à 21. Lorsque la souris est relâchée plus tard et que la première boîte de dialogue est fermée, une deuxième boîte de dialogue apparaît.

  2. Plus la souris est enfoncée, plus la valeur signalée est élevée, jusqu'au maximum.

Pour référence à vérifier votre version, le code correspondant mentionné dans le bug report est quatre appels à autoRepeatTimer.stop() dans le private static class ArrowButtonHandler trouvés dans BasicSpinnerUI. L'effet varie selon la version du JDK et peut être un artefact de la fréquence à laquelle la flèche peut se répéter dans le délai initial choisi.

autoRepeatTimer.setInitialDelay(300); 
+0

Je ne comprends pas très bien votre réponse à ce que je ferais pour résoudre ce problème. Y at-il quelque part que je suis supposé appeler autoRepeatTimer.setInitialDelay (300)? – Thunderforge

+0

Je rapporte mes résultats sur les versions 5 et 6 de JDK. Voyez-vous une régression? Je ne vois pas de meilleure solution. Pourquoi utiliser une boîte de dialogue modale pour signaler le dépassement du seuil? Je le signalerais ailleurs via 'PropertyChangeListener', pour [exemple] (http://stackoverflow.com/a/11832979/230513). – trashgod

Questions connexes