从 jTextField 获取最终文本的预览
Getting preview of final text from jTextField
我正在尝试创建 JTextField
通过此检查只能接受双精度数(包括科学记数法):
abstract class DoubleKeyAdapter extends KeyAdapter
{
@Override
public void KeyTyped(KeyEvent e)
{
if (!(((JTextField) e.getSource()).getText() + e.getKeyChar()).matches(“[+-]?\d*(\.\d*)?([eE][+-]?\d*)?”))
e.consume();
}
@Override
public abstract void KeyReleased(KeyEvent e);
}
问题是当我尝试将 -
添加到文本字段的开头时。它不允许我这样做,因为它通过在文本末尾附加 -
来进行检查,换句话说,我不知道新字符添加到哪里。
所以我的问题是:
- 有没有办法在文本出现在文本字段之前预览整个文本?
- 有没有更好的方法来创建
JTextField
(或它的扩展)?
- 有没有办法知道新角色的位置?
您可以为此使用 DocumentFilter
。
它允许您在将文本插入文档之前进行编辑。
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class DoubleFilter extends DocumentFilter
{
@Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributes)
throws BadLocationException
{
replace(fb, offset, 0, text, attributes);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attributes)
throws BadLocationException
{
// In case someone tries to clear the Document by using setText(null)
if (text == null)
text = "";
// Build the text string assuming the replace of the text is successfull
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder();
sb.append(doc.getText(0, doc.getLength()));
sb.replace(offset, offset + length, text);
if (validReplace(sb.toString()))
super.replace(fb, offset, length, text, attributes);
else
Toolkit.getDefaultToolkit().beep();
}
private boolean validReplace(String text)
{
// In case setText("") is used to clear the Document
if (text.isEmpty())
return true;
// Verify input is a Double
try
{
Double.parseDouble( text );
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
private static void createAndShowGUI()
{
JTextField textField = new JTextField(10);
AbstractDocument doc = (AbstractDocument) textField.getDocument();
doc.setDocumentFilter( new DoubleFilter() );
textField.setText("123");
textField.setText("123567");
textField.setText(null);
JFrame frame = new JFrame("Integer Filter");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout( new java.awt.GridBagLayout() );
frame.add( textField );
frame.setSize(220, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
它并不能满足您的所有需求,但可以帮助您入门。
我对解决方案的看法,受到@camickr 的启发,
并添加了 2 种方法:getDouble()
和 setDouble()
import javax.swing.*;
import javax.swing.text.*;
import java.util.regex.Pattern;
public class JDoubleField extends JTextField
{
private static final DocumentFilter doubleFilter = new DocumentFilter()
{
private final Pattern pattern = Pattern.compile("[+-]?(NaN|Infinity|\d*(\.\d*)?((?<=\d\.?)[eE][+-]?\d*)?)");
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException
{
replace(fb, offset, 0, string, attr);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException
{
if (text == null || pattern.matcher(new StringBuilder(fb.getDocument().getText(0, fb.getDocument().getLength()))
.replace(offset, offset + length, text))
.matches())
super.replace(fb, offset, length, text, attrs);
}
};
public double getDouble()
{
try
{
return Double.parseDouble(getText());
} catch (NumberFormatException ignored)
{
return Double.NaN;
}
}
public void setDouble(double num)
{
setText(String.valueOf(num));
}
public JDoubleField()
{
this(0);
}
public JDoubleField(double num)
{
this(String.valueOf(num));
}
public JDoubleField(double num, int columns)
{
this(String.valueOf(num), columns);
}
public JDoubleField(Document doc, double num, int columns)
{
this(doc, String.valueOf(num), columns);
}
public JDoubleField(int columns)
{
this(null, columns);
}
public JDoubleField(String text)
{
this(text, 0);
}
public JDoubleField(String text, int columns)
{
this(null, text, columns);
}
public JDoubleField(Document doc, String text, int columns)
{
super(doc, null, columns);
((AbstractDocument) getDocument()).setDocumentFilter(doubleFilter);
if (text != null)
setText(text);
}
}
我正在尝试创建 JTextField
通过此检查只能接受双精度数(包括科学记数法):
abstract class DoubleKeyAdapter extends KeyAdapter
{
@Override
public void KeyTyped(KeyEvent e)
{
if (!(((JTextField) e.getSource()).getText() + e.getKeyChar()).matches(“[+-]?\d*(\.\d*)?([eE][+-]?\d*)?”))
e.consume();
}
@Override
public abstract void KeyReleased(KeyEvent e);
}
问题是当我尝试将 -
添加到文本字段的开头时。它不允许我这样做,因为它通过在文本末尾附加 -
来进行检查,换句话说,我不知道新字符添加到哪里。
所以我的问题是:
- 有没有办法在文本出现在文本字段之前预览整个文本?
- 有没有更好的方法来创建
JTextField
(或它的扩展)? - 有没有办法知道新角色的位置?
您可以为此使用 DocumentFilter
。
它允许您在将文本插入文档之前进行编辑。
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class DoubleFilter extends DocumentFilter
{
@Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributes)
throws BadLocationException
{
replace(fb, offset, 0, text, attributes);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attributes)
throws BadLocationException
{
// In case someone tries to clear the Document by using setText(null)
if (text == null)
text = "";
// Build the text string assuming the replace of the text is successfull
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder();
sb.append(doc.getText(0, doc.getLength()));
sb.replace(offset, offset + length, text);
if (validReplace(sb.toString()))
super.replace(fb, offset, length, text, attributes);
else
Toolkit.getDefaultToolkit().beep();
}
private boolean validReplace(String text)
{
// In case setText("") is used to clear the Document
if (text.isEmpty())
return true;
// Verify input is a Double
try
{
Double.parseDouble( text );
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
private static void createAndShowGUI()
{
JTextField textField = new JTextField(10);
AbstractDocument doc = (AbstractDocument) textField.getDocument();
doc.setDocumentFilter( new DoubleFilter() );
textField.setText("123");
textField.setText("123567");
textField.setText(null);
JFrame frame = new JFrame("Integer Filter");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout( new java.awt.GridBagLayout() );
frame.add( textField );
frame.setSize(220, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
它并不能满足您的所有需求,但可以帮助您入门。
我对解决方案的看法,受到@camickr 的启发,
并添加了 2 种方法:getDouble()
和 setDouble()
import javax.swing.*;
import javax.swing.text.*;
import java.util.regex.Pattern;
public class JDoubleField extends JTextField
{
private static final DocumentFilter doubleFilter = new DocumentFilter()
{
private final Pattern pattern = Pattern.compile("[+-]?(NaN|Infinity|\d*(\.\d*)?((?<=\d\.?)[eE][+-]?\d*)?)");
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException
{
replace(fb, offset, 0, string, attr);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException
{
if (text == null || pattern.matcher(new StringBuilder(fb.getDocument().getText(0, fb.getDocument().getLength()))
.replace(offset, offset + length, text))
.matches())
super.replace(fb, offset, length, text, attrs);
}
};
public double getDouble()
{
try
{
return Double.parseDouble(getText());
} catch (NumberFormatException ignored)
{
return Double.NaN;
}
}
public void setDouble(double num)
{
setText(String.valueOf(num));
}
public JDoubleField()
{
this(0);
}
public JDoubleField(double num)
{
this(String.valueOf(num));
}
public JDoubleField(double num, int columns)
{
this(String.valueOf(num), columns);
}
public JDoubleField(Document doc, double num, int columns)
{
this(doc, String.valueOf(num), columns);
}
public JDoubleField(int columns)
{
this(null, columns);
}
public JDoubleField(String text)
{
this(text, 0);
}
public JDoubleField(String text, int columns)
{
this(null, text, columns);
}
public JDoubleField(Document doc, String text, int columns)
{
super(doc, null, columns);
((AbstractDocument) getDocument()).setDocumentFilter(doubleFilter);
if (text != null)
setText(text);
}
}