对于任务,我需要使用以下行为创建JFormattedTextField:
我似乎无法找到正确的听众组合来实现这一目标。我尝试使用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);
}
}
这几乎可以满足我的一切需求。但问题是ENTER键永远不会被捕获。我认为它在到达我的KeyListener之前被消耗了,但是我怎么能阻止它?
即使可以防止这种情况,我仍然觉得应该有更清洁的原因来完成上面的代码。
答案 0 :(得分:4)
尝试使用此代码示例,告诉我这是您想要的行为,或者您期待的是其他内容,除此之外:
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();
}
});
}
}