Java JFormattedTextfield仅在按enter键时验证

Java JFormattedTextfield仅在按enter键时验证,java,swing,jformattedtextfield,Java,Swing,Jformattedtextfield,对于任务,我需要创建具有以下行为的JFormattedTextField: 如果该值已编辑且不等于上次验证的值,则背景必须变为黄色 价值验证可随时进行 如果焦点丢失,则不会发生任何事情(如果背景为黄色,则应保持黄色,…) 按下Enter键时应采取措施 我似乎找不到正确的听众组合来实现这一点。我试着使用KeyAdapter,InputVerifier和PropertyChangeListener,但这给了我非常难看的代码,它只能工作80% 如何做到这一点 编辑:我写了一个小例子: import

对于任务,我需要创建具有以下行为的JFormattedTextField:

  • 如果该值已编辑且不等于上次验证的值,则背景必须变为黄色
  • 价值验证可随时进行
  • 如果焦点丢失,则不会发生任何事情(如果背景为黄色,则应保持黄色,…)
  • 按下Enter键时应采取措施
我似乎找不到正确的听众组合来实现这一点。我试着使用
KeyAdapter
InputVerifier
PropertyChangeListener
,但这给了我非常难看的代码,它只能工作80%

如何做到这一点

编辑:我写了一个小例子:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.text.ParseException;

import javax.swing.AbstractAction;
import javax.swing.InputVerifier;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test extends JPanel {

    private JFormattedTextField field;
    private JLabel label;
    private JButton btn;

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

        label = new JLabel("Enter a float value:");
        btn = new JButton(new AbstractAction("Print to stdout"){

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(field.getValue());
            }

        });
        field = new JFormattedTextField(new Float(9.81));

        field.addKeyListener(new KeyAdapter(){

            @Override
            public void keyPressed(KeyEvent e){
                field.setBackground(Color.YELLOW);
            }

            @Override 
            public void keyTyped(KeyEvent e){
                if(e.getKeyCode() == KeyEvent.VK_ENTER){
                    try{
                        field.commitEdit();
                        field.setBackground(Color.WHITE);
                    }catch(ParseException e1){
                        field.setBackground(Color.RED);
                    }
                }
            }
        });

        field.setInputVerifier(new InputVerifier(){

            @Override
            public boolean verify(JComponent comp) {
                try{
                    field.commitEdit();
                    field.setBackground(Color.YELLOW);
                    return true;
                }catch(ParseException e){
                    field.setBackground(Color.RED);
                    return false;
                }
            }

        });

        add(label, BorderLayout.NORTH);
        add(field, BorderLayout.CENTER);
        add(btn, BorderLayout.SOUTH);
    }


    public static void main(String[] args) {
        JFrame window = new JFrame("InputVerifier test program");
        Container cp = window.getContentPane();
        cp.add(new Test());
        window.pack();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true);
    }
}
这几乎是我想要的一切。但问题是,回车键从未被捕获。我认为它在到达我的KeyListener之前就已经被消耗掉了,但是我如何才能防止呢


即使这是可以避免的,我仍然觉得应该有一个更清晰的理由来完成上述代码所做的事情。

尝试一下这个代码示例,告诉我这是期望的行为,还是您期望的其他行为,而不是:

import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

public class JFormattedExample
{
    private String lastValidValue;

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("JFormattedTextField Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        final JFormattedTextField ftf = new JFormattedTextField(
                            NumberFormat.getNumberInstance());
        ftf.setColumns(10);
        ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);
        ftf.setValue(100);
        lastValidValue = "100";
        ftf.addCaretListener(new CaretListener()
        {
            public void caretUpdate(CaretEvent ce)
            {
                System.out.println("Last Valid Value : " + lastValidValue);
                if (ftf.isEditValid())
                {
                    String latestValue = ftf.getText();
                    System.out.println("Latest Value : " + latestValue);
                    if (!(latestValue.equals(lastValidValue)))
                        ftf.setBackground(Color.YELLOW.darker());
                    else
                    {
                        lastValidValue = ftf.getText();
                        ftf.setBackground(Color.WHITE);
                    }
                }
                else
                {
                    System.out.println("Invalid Edit Entered.");
                }
            }
        });

        contentPane.add(ftf);
        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new JFormattedExample().createAndDisplayGUI();
            }
        });
    }
}

请尝试此代码示例,告诉我这是您想要的行为,还是您期望的其他行为,而不是:

import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

public class JFormattedExample
{
    private String lastValidValue;

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("JFormattedTextField Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        final JFormattedTextField ftf = new JFormattedTextField(
                            NumberFormat.getNumberInstance());
        ftf.setColumns(10);
        ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);
        ftf.setValue(100);
        lastValidValue = "100";
        ftf.addCaretListener(new CaretListener()
        {
            public void caretUpdate(CaretEvent ce)
            {
                System.out.println("Last Valid Value : " + lastValidValue);
                if (ftf.isEditValid())
                {
                    String latestValue = ftf.getText();
                    System.out.println("Latest Value : " + latestValue);
                    if (!(latestValue.equals(lastValidValue)))
                        ftf.setBackground(Color.YELLOW.darker());
                    else
                    {
                        lastValidValue = ftf.getText();
                        ftf.setBackground(Color.WHITE);
                    }
                }
                else
                {
                    System.out.println("Invalid Edit Entered.");
                }
            }
        });

        contentPane.add(ftf);
        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new JFormattedExample().createAndDisplayGUI();
            }
        });
    }
}

你是说?请编辑您的问题,使其包含一个显示您迄今为止尝试过的内容的字段。您能否进一步解释这行内容“如果值已编辑且不等于上次验证的值”,这是否意味着
JFormattedTextField
只能取一个合法值。除此之外的任何东西,即使有效,也会引起颜色的变化。假设该字段包含“9.81”。当用户键入'9.811'后加上退格(因此该字段现在包含'9.81')时,该字段不应更改颜色。啊哈,那么您想在运行时检查输入的有效性,也就是说,是这样吗?您键入了一些内容,希望直接检查有效性。好的,既然你发布了你的代码,让我检查一下:-)看看粘贴的代码,这是你想要的,还是其他我无法理解的东西,通过你提供的信息。你的意思是?请编辑您的问题,使其包含一个显示您迄今为止尝试过的内容的字段。您能否进一步解释这行内容“如果值已编辑且不等于上次验证的值”,这是否意味着
JFormattedTextField
只能取一个合法值。除此之外的任何东西,即使有效,也会引起颜色的变化。假设该字段包含“9.81”。当用户键入'9.811'后加上退格(因此该字段现在包含'9.81')时,该字段不应更改颜色。啊哈,那么您想在运行时检查输入的有效性,也就是说,是这样吗?您键入了一些内容,希望直接检查有效性。好的,既然你发布了你的代码,让我检查一下:-)看看粘贴的代码,这是你想要的,还是其他一些我无法理解的,由你提供的信息。