2010-02-10 17 views
3

Je souhaite utiliser un JFormattedTextField pour permettre à l'utilisateur d'entrer l'heure durée valeurs dans un formulaire. Les valeurs valides exemples sont:JFormattedTextField: valeur de durée de l'entrée

2h 30m
72h 15m
6h
0h

Cependant je rencontre un succès limité avec cela. Quelqu'un peut-il s'il vous plaît suggérer comment cela peut être accompli? Je suis OK si ce résultat peut être atteint en utilisant un JTextField ainsi.

Merci!


S'il vaut rien, voici ma tentative actuelle:

mFormattedText.setFormatterFactory(
    new DefaultFormatterFactory(
     new DateFormatter(
      new SimpleDateFormat("H mm")))); 

Cela fonctionne sorta sauf que:

  • Je ne peux pas obtenir h et m apparaître sous forme de texte (J'ai essayé d'échapper) *
  • Le nombre d'heures a un maximum

*: Voir @ réponse Nanda

Répondre

1

Le code:

public static void main(String[] args) { 
    JFrame jFrame = new JFrame(); 
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    jFrame.setLayout(new BorderLayout()); 
    jFrame.setPreferredSize(new Dimension(500, 500)); 

    final JFormattedTextField comp = new JFormattedTextField(); 
    comp.setFormatterFactory(new DefaultFormatterFactory(new DateFormatter(new SimpleDateFormat(
      "H'h' mm'm'")))); 
    comp.setValue(Calendar.getInstance().getTime()); 

    comp.addPropertyChangeListener("value", new PropertyChangeListener() { 

     @Override public void propertyChange(PropertyChangeEvent evt) { 
      System.out.println(comp.getValue()); 

     } 
    }); 

    jFrame.getContentPane().add(comp, BorderLayout.CENTER); 

    jFrame.pack(); 
    jFrame.setVisible(true); 
} 
0

hmm, ce que je pense est que vous pouvez atteindre le même objectif en créant trois différentes JTextField pour tous les trois composants de temps, une pour l'heure, minute et seconde (si c'est inclus) pour obtenir votre contribution ... juste une pensée, vous pouvez simplement les concaténer si vous le souhaitez ... juste une pensée ...

+0

@ultrajohn, merci pour votre contribution, mais sa partie des exigences qu'il doit être dans un domaine, et que le format est tel que je l'ai décrit dans la question. – bguiz

1

Avez-vous essayé H'h' mm'm'?

+0

+1 Fonctionne également avec 'InputVerifier'. – trashgod

+0

@nanda, Merci de m'avoir expliqué comment échapper les caractères (fonctionné), mais ce qui n'a pas fonctionné, c'est que je veux que les utilisateurs entrent '6h 42m', et que ça aboutisse à 'Date nonparable:" 6h 42m "', donc je suis toujours coincé. Cela ne fonctionne que lorsque l'utilisateur entre quelque chose comme '6:42:00 AM ', ce qui ne fonctionne pas pour moi puisque l'intention est d'entrer une durée. – bguiz

+0

@trashgod, pourriez-vous suggérer comment utiliser 'InputVerifier' dans ce scénario? – bguiz

4

Voici un exemple d'utilisation de InputVerifier pour prendre en charge plusieurs formats d'entrée.

import java.awt.EventQueue; 
import java.text.NumberFormat; 
import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Date; 
import java.util.List; 
import javax.swing.Box; 
import javax.swing.InputVerifier; 
import javax.swing.JComponent; 
import javax.swing.JFormattedTextField; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.text.DateFormatter; 
import javax.swing.text.DefaultFormatterFactory; 

public class FormattedFields { 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      //@Override 
      public void run() { 
       new FormattedFields(); 
      } 
     }); 
    } 

    FormattedFields() { 
     Box form = Box.createVerticalBox(); 

     form.add(new JLabel("Date & Time:")); 
     DateTimeField dtField = new DateTimeField(new Date()); 
     form.add(dtField); 

     form.add(new JLabel("Amount:")); 
     JFormattedTextField amtField = new JFormattedTextField(
      NumberFormat.getCurrencyInstance()); 
     amtField.setValue(100000); 
     form.add(amtField); 

     JFrame frame = new JFrame(); 
     frame.add(form); 
     frame.pack(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
    } 
} 

class DateTimeField extends JFormattedTextField { 

    public DateTimeField() { 
     super(DateTimeVerifier.getDefaultFormat()); 
     this.setInputVerifier(new DateTimeVerifier(this)); 
    } 

    public DateTimeField(Date date) { 
     this(); 
     this.setValue(date); 
    } 

    @Override 
    protected void invalidEdit() { 
     if (!this.getInputVerifier().verify(this)) { 
      super.invalidEdit(); 
     } 
    } 
} 

class DateTimeVerifier extends InputVerifier { 

    private static List<SimpleDateFormat> validForms = 
     new ArrayList<SimpleDateFormat>(); 


    static { 
     validForms.add(new SimpleDateFormat("dd-MMM-yyyy HH'h':mm'm'")); 
     validForms.add(new SimpleDateFormat("dd-MMM-yyyy HH:mm")); 
    } 
    private JFormattedTextField tf; 
    private Date date; 

    public DateTimeVerifier(JFormattedTextField tf) { 
     this.tf = tf; 
    } 

    @Override 
    public boolean verify(JComponent input) { 
     boolean result = false; 
     if (input == tf) { 
      String text = tf.getText(); 
      for (SimpleDateFormat format : validForms) { 
       try { 
        date = format.parse(text); 
        result |= true; 
       } catch (ParseException pe) { 
        result |= false; 
       } 
      } 
     } 
     return result; 
    } 

    @Override 
    public boolean shouldYieldFocus(JComponent input) { 
     if (verify(input)) { 
      tf.setValue(date); 
      return true; 
     } else { 
      return false; 
     } 
    } 

    public static SimpleDateFormat getDefaultFormat() { 
     return validForms.get(0); 
    } 
} 
0

tl; dr

Duration.parse("PT2H30M") 

ISO 8601

Si vous êtes prêt à redéfinir vos formats d'entrée souhaités, je suggère d'utiliser le déjà- formats existants définis par la norme ISO 8601.

Le modèle PnYnMnDTnHnMnS utilise un P pour marquer le début, un T pour séparer toute partie années-mois-jours de toute partie heures-minutes-secondes.

Une heure et demie est PT1H30M, par exemple.

java.time

Les classes java.time utilisent les formats ISO 8601 par défaut lors de l'analyse/génération de chaînes.Cela inclut les classes Period et Duration pour représenter les plages de temps non liées à la chronologie.

Duration d = Duration.ofHours(1).plusMinutes(30); 
String output = d.toString(); 

Aller dans l'autre direction, analyser une chaîne.

Duration d = Duration.parse("PT1H30M"); 

Voir live code in IdeOne.com.

Voir my similar Answer à similar Question.


A propos java.time

Le cadre java.time est construit en Java 8 et versions ultérieures. Ces classes supplantent les classes date de temps anciens legacy gênants tels que java.util.Date, Calendar, & SimpleDateFormat. Le projet Joda-Time, maintenant en maintenance mode, conseille la migration vers les classes java.time.

Pour en savoir plus, voir le Oracle Tutorial. Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310.

Où obtenir les classes java.time?

  • Java SE 8 et SE 9 et plus tard
    • intégré.
    • Partie de l'API Java standard avec une implémentation groupée.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et SE 7
    • Une grande partie de la fonctionnalité de java.time est de retour à Java 6 Ported .
  • Android

Le projet ThreeTen-Extra java.time étend avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels ajouts futurs à java.time. Vous pouvez trouver ici des classes utiles telles que Interval, YearWeek, YearQuarter et more.