Frage

I've got a GUI window asking for time spent on a break. The outcome that I would like to get is, for example, 1:15 - int hours = 1 and int mins = 15 - after you click the continue button. The outcome I'm getting is either hours, or mins, because I can't make JComboBox and JButton work together (I think). Also, I don't quite know how to check whether user entered a number or an invalid input. Here is the code:

@SuppressWarnings("serial")
public class FormattedTextFields extends JPanel implements ActionListener {

    private int hours;
    private JLabel hoursLabel;
    private JLabel minsLabel;
    private static String hoursString = " hours: ";
    private static String minsString = " minutes: ";
    private JFormattedTextField hoursField;
    private NumberFormat hoursFormat;

    public FormattedTextFields() {

        super(new BorderLayout());
        hoursLabel = new JLabel(hoursString);
        minsLabel = new JLabel(minsString);
        hoursField = new JFormattedTextField(hoursFormat);
        hoursField.setValue(new Integer(hours));
        hoursField.setColumns(10);
        hoursLabel.setLabelFor(hoursField);
        minsLabel.setLabelFor(minsLabel);

        JPanel fieldPane = new JPanel(new GridLayout(0, 2));

        JButton cntButton = new JButton("Continue");
        cntButton.setActionCommand("cnt");
        cntButton.addActionListener(this);
        JButton prevButton = new JButton("Back");

        String[] quarters = { "15", "30", "45" };

        JComboBox timeList = new JComboBox(quarters);
        timeList.setSelectedIndex(2);
        timeList.addActionListener(this);

        fieldPane.add(hoursField);
        fieldPane.add(hoursLabel);
        fieldPane.add(timeList);
        fieldPane.add(minsLabel);
        fieldPane.add(prevButton);
        fieldPane.add(cntButton);

        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        add(fieldPane, BorderLayout.CENTER);
    }

    private static void createAndShowGUI() {    
        JFrame frame = new JFrame("FormattedTextFieldDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new FormattedTextFields());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                UIManager.put("swing.boldMetal", Boolean.FALSE);
                createAndShowGUI();
            }
        });
    }

    @Override
    public void actionPerformed(ActionEvent e) {    
        if (e.getActionCommand().equalsIgnoreCase("cnt")) {

        hours = ((Number) hoursField.getValue()).intValue();
        minutes = Integer.parseInt(timeList.getSelectedItem().toString());

        // \d mean every digit charater
        Pattern p = Pattern.compile("\\d");
        Matcher m = p.matcher(hoursField.getValue().toString());
        if (m.matches()) {
            System.out.println("Hours: " + hours);
            System.out.println("Minutes: " + minutes);
        } else {
            hoursField.setValue(0);
            JOptionPane.showMessageDialog(null, "Numbers only please.");
        }
        }
    }

} // end class

--EDIT--
updated ActionPerformed method

War es hilfreich?

Lösung

You need a valid reference to the combo box that is visible in the action listener for the ActionListener to be able to call methods on it and extract the value it is holding. Currently your JComboBox is declared in the class's constructor and so is only visible in the constructor and no where else. To solve this the combo box needs to be a class field, meaning it is declared in the class itself, not some method or constructor.

For example:

import java.awt.event.*;
import javax.swing.*;

public class Foo002 extends JPanel implements ActionListener {

   JComboBox combo1 = new JComboBox(new String[]{"Fe", "Fi", "Fo", "Fum"});
   public Foo002() {

      JComboBox combo2 = new JComboBox(new String[]{"One", "Two", "Three", "Four"});
      JButton helloBtn = new JButton("Hello");

      helloBtn.addActionListener(this); // I really hate doing this!

      add(combo1);
      add(combo2);
      add(helloBtn);
   }

   private static void createAndShowGUI() {
      JFrame frame = new JFrame("FormattedTextFieldDemo");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(new Foo002());
      frame.pack();
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            UIManager.put("swing.boldMetal", Boolean.FALSE);
            createAndShowGUI();
         }
      });
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      // this works because combo1 is visible in this method 
      System.out.println(combo1.getSelectedItem().toString());

      // this doesn't work because combo2's scope is limited to 
      // the constructor and it isn't visible in this method.
      System.out.println(combo2.getSelectedItem().toString());
   }

}

Andere Tipps

For the parsing number test, you have two solutions:

first:

try{
    Integer.parseInt(myString);
catch(Exception e){
    System.out.print("not a number");
}

second: and I think cleaner way is to use regex:

// \d mean every digit charater you can find a full description [here][1] 
Pattern p = Pattern.compile("\\d");
Matcher m = p.matcher( myString );
if( m.matches() ){
    //it's a number
}else{
    //it's not a number
}

if you want to do stronger regexp, take a look at this java regex tester.

good night & good luck

PS: there no problem with making interaction beetween graphics elements, you just need to keep references of your graphical objects.

Check this snippet out, added some comments to provide information on the NumberFormat thingy and displaying the Time at the click of Continue button. Since the type of checking you wanted to apply, I did that on a simple JTextField no need for JFormattedTextField for this thing.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class FormattedTextFields extends JPanel implements ActionListener 
{

    private int hours;
    private JLabel hoursLabel;
    private JLabel minsLabel;
    private static String hoursString = " hours: ";
    private static String minsString = " minutes: ";
    private JComboBox timeList;
    private JTextField hoursField;

    public FormattedTextFields() 
    {
        super(new BorderLayout());

        hoursLabel = new JLabel(hoursString);
        minsLabel = new JLabel(minsString);
        hoursField = new JTextField();
        //hoursField.setValue(new Integer(hours));
        hoursField.setColumns(10);
        hoursLabel.setLabelFor(hoursField);
        minsLabel.setLabelFor(minsLabel);
        Document doc = hoursField.getDocument();
        if (doc instanceof AbstractDocument)
        {
            AbstractDocument abDoc  = (AbstractDocument) doc;
            abDoc.setDocumentFilter(new DocumentInputFilter());
        }

        JPanel fieldPane = new JPanel(new GridLayout(0, 2));

        JButton cntButton = new JButton("Continue");
        cntButton.setActionCommand("cnt");
        cntButton.addActionListener(this);
        JButton prevButton = new JButton("Back");

        String[] quarters = { "15", "30", "45" };

        /*
         * Declared timeList as an Instance Variable, so that 
         * it can be accessed inside the actionPerformed(...)
         * method.
         */
        timeList = new JComboBox(quarters);
        timeList.setSelectedIndex(2);
        timeList.addActionListener(this);

        fieldPane.add(hoursField);
        fieldPane.add(hoursLabel);
        fieldPane.add(timeList);
        fieldPane.add(minsLabel);
        fieldPane.add(prevButton);
        fieldPane.add(cntButton);

        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        add(fieldPane, BorderLayout.CENTER);
    }

    private static void createAndShowGUI() 
    {    
        JFrame frame = new JFrame("FormattedTextFieldDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new FormattedTextFields());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                UIManager.put("swing.boldMetal", Boolean.FALSE);
                createAndShowGUI();
            }
        });
    }

    @Override
    public void actionPerformed(ActionEvent e) 
    {

        String time = "";
        if (e.getActionCommand().equalsIgnoreCase("cnt")) 
        {
            hours = Integer.parseInt(hoursField.getText());
            time = hours + " : " + ( (String) timeList.getSelectedItem());
            System.out.println(time);
        }
    }

    /*
     * This class will check for any invalid input and present 
     * a Dialog Message to user, for entering appropriate input.
     * you can let it make sound when user tries to enter the
     * invalid input. Do see the beep() part for that inside 
     * the class's body.
     */
    class DocumentInputFilter extends DocumentFilter
    {
        public void insertString(FilterBypass fb
                    , int offset, String text, AttributeSet as) throws BadLocationException
        {
            int len = text.length();
            if (len > 0)
            {
                /* Here you can place your other checks
                 * that you need to perform and do add
                 * the same checks for replace method
                 * as well.
                 */
                if (Character.isDigit(text.charAt(len - 1)))
                    super.insertString(fb, offset, text, as);
                else 
                {
                    JOptionPane.showMessageDialog(null, "Please Enter a valid Integer Value."
                                                            , "Invalid Input : ", JOptionPane.ERROR_MESSAGE);
                    Toolkit.getDefaultToolkit().beep();
                }   
            }                                               
        }

        public void replace(FilterBypass fb, int offset
                            , int length, String text, AttributeSet as) throws BadLocationException
        {
            int len = text.length();
            if (len > 0)
            {
                if (Character.isDigit(text.charAt(len - 1)))
                    super.replace(fb, offset, length, text, as);
                else 
                {
                    JOptionPane.showMessageDialog(null, "Please Enter a valid Integer Value."
                                                            , "Invalid Input : ", JOptionPane.ERROR_MESSAGE);
                    Toolkit.getDefaultToolkit().beep();
                }
            }                                               
        }
    }

} // end class
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top