格式化文本字段和JComboBox在一起

时间:2012-02-26 00:35:58

标签: java swing user-interface combobox jformattedtextfield

我有一个GUI窗口,询问休息时间。我想得到的结果是,例如,1:15 - int hours = 1和int mins = 15 - 单击继续按钮后。我得到的结果要么是小时,要么是分钟,因为我不能让JComboBox和JButton一起工作(我想)。另外,我不太清楚如何检查用户是输入了数字还是输入了无效的输入。这是代码:

@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

- 编辑 -
  更新了ActionPerformed方法

3 个答案:

答案 0 :(得分:7)

您需要对动作侦听器中可见的组合框的有效引用,以便ActionListener能够在其上调用方法并提取它所持有的值。目前,您的JComboBox在类的构造函数中声明,因此仅在构造函数中可见,而在其他位置不可见。要解决这个问题,组合框需要是一个类字段,这意味着它在类本身中声明,而不是某些方法或构造函数。

例如:

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());
   }

}

答案 1 :(得分:3)

对于解析数测试,您有两个解决方案:

第一

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

第二:我认为更清洁的方法是使用正则表达式:

// \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
}

如果您想要更强大的正则表达式,请查看此java regex tester

晚安&祝你好运

PS:在图形元素之间进行交互没有问题,您只需要保留图形对象的引用。

答案 2 :(得分:2)

检查此代码段,添加一些注释以提供有关NumberFormat的信息,并在单击“继续”按钮时显示时间。由于你想要应用的检查类型,我在一个简单的JTextField上做了这个,不需要JFormattedTextField。

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