Форматированное текстовое поле и JComboBox вместе - PullRequest
3 голосов
/ 26 февраля 2012

У меня есть окно с графическим интерфейсом, запрашивающее время, проведенное в перерыве. Результат, который я хотел бы получить, например, 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

- EDIT -
обновленный метод ActionPerformed

Ответы [ 3 ]

7 голосов
/ 26 февраля 2012

Вам нужна действительная ссылка на поле со списком, которое отображается в приемнике действий, чтобы 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());
   }

}
3 голосов
/ 26 февраля 2012

Для теста числа разбора у вас есть два решения:

первый:

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-регулярных выражений .

спокойной ночи и удачи

PS: нет проблем с взаимодействием между графическими элементами, вам просто нужно хранить ссылки на ваши графические объекты.

2 голосов
/ 26 февраля 2012

Проверьте этот фрагмент, добавьте несколько комментариев, чтобы предоставить информацию о 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
...