当我输入TextField 7字符时,光标会自动移动到下一个TextField。但在我的代码中,我的光标没有转到nextField。 (我知道我不能使用addKeyListener,因此尝试将DocumentListener用于此代码)
lbltext1 = new JLabel("Text1");
panel.add(lbltext1, "cell 0 1,alignx trailing");
final int maxSize =7 ;
for (int i = 0; i < 1; i++) {
final JTextField txtText1 = new JTextField();
NavigationFilter filter = new NavigationFilter() {
@Override
public void setDot(FilterBypass fb, int dot, Bias bias) {
if (dot >= maxSize) {
fb.setDot(0, bias);
txtText1.transferFocus();
return;
}
fb.setDot(dot, bias);
}
@Override
public void moveDot(FilterBypass fb, int dot, Bias bias) {
if (dot >= maxSize) {
fb.setDot(0, bias);
txtText1.transferFocus();
return;
}
fb.moveDot(dot, bias);
}
};
txtText1.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent arg0) {
if (txtText1.getText().equals("")) {
txtDate.setText("");
} else {
SwingWorker<?, ?> job = new UIQuery();
job.execute();
}
}
});
txtText1.setNavigationFilter(filter);
((AbstractDocument) txtText1.getDocument()).setDocumentFilter(new DocumentSizeFilter(maxSize));
panel.add(txtText1, "cell 1 1,growx");
txtText1.setColumns(10);
}
JLabel lblText2 = new JLabel("Production Date");
panel.add(lblText2, "cell 0 2,alignx trailing");
txtText2 = new JTextField();
panel.add(txtText2, "flowx,cell 1 2,growx");
txtText2.setColumns(10);
txtText2.addFocusListener(new TextBoxGainedFocusEventSinglePreview());
txtText2.getDocument().addDocumentListener(new TextBoxDataChangedEventSinglePreview());
请告知我该如何修改它。 感谢
答案 0 :(得分:2)
所以,这是一个简单的概念证明,当场的Document
长度> 6
import java.awt.KeyboardFocusManager;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JTextField field1 = new JTextField(7);
JTextField field2 = new JTextField(7);
add(field1);
add(field2);
field1.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
if (e.getDocument().getLength() > 6) {
//field1.transferFocus();
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
}
}
@Override
public void removeUpdate(DocumentEvent e) {
}
@Override
public void changedUpdate(DocumentEvent e) {
if (e.getDocument().getLength() > 6) {
//field1.transferFocus();
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
}
}
});
}
}
}
当某些东西不起作用时,首先删除测试它不需要的所有东西(即DocumentFilter
和NavigationFilter
),让它尽可能地处于隔离状态,一旦你知道它正在工作,一次重新引入其他元素并确保没有任何破坏。
DocumentSizeFilter
可能会干扰它,但我没有足够的背景来100%确定
答案 1 :(得分:1)
不知道更好的设计是什么:
你有第一种方法的解决方案。
对于第二种方法,您可以查看:
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.AbstractDocument;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;
import javax.swing.text.JTextComponent;
/**
* A DocumentFilter that allows you to control the maximum number of
* characters that can be added to the Document. When the Document is
* full you can optionally tab to the next component to speed data entry.
*
* This class can also be used as a generic size filter for JTextFields. In
* this case when a size of 0 is speicifed for the size of the Document the
* getColumns() method of JTextField will be used to determine the size
* restriction.
*/
public class TabDocumentFilter extends DocumentFilter
{
private int size;
private boolean autoTab = true;
/**
* Generic constructor for use with JTextFields only. The size of the
* Document will be determined by the value of the getColumns() method.
*/
public TabDocumentFilter()
{
this(0);
}
/**
* Constructor to set the size for this filter
*
* @param size maximum number of characters to be added to the Document
*/
public TabDocumentFilter(int size)
{
setSize( size );
}
/**
* Get the auto tab property
*
* @return the auto tab property
*/
public boolean getAutoTab()
{
return autoTab;
}
/**
* Set the auto tab property
*
* @param autoTab the default is true
*/
public void setAutoTab(boolean autoTab)
{
this.autoTab = autoTab;
}
/**
* Get the maximum size for any Document using this filter
*
* @return
*/
public int getSize()
{
return size;
}
/**
* Set maximum size for a Document using this filter. Dynamically changing
* the size will not affect existing Documents. Characters will not be
* removed from any Document. The filter will only be invoked on new
* additions to the Document.
*
* @param size the maximum number of character allowed in the Document
*/
public void setSize(int size)
{
this.size = size;
}
/**
* Install this filter on the AbstractDocument
*
* @param components the text components that will use this filter
*/
public void installFilter(JTextComponent... components)
{
for (JTextComponent component : components)
{
Document doc = component.getDocument();
if (doc instanceof AbstractDocument)
{
((AbstractDocument)doc).setDocumentFilter( this );
}
}
}
/**
* Make sure the insertion of text will not cause the Document to exceed
* its size limit. Also, potentially tab to next component when full.
*/
@Override
public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
throws BadLocationException
{
int possibleSize = fb.getDocument().getLength() + str.length();
int allowedSize = getAllowedSize( fb );
if (possibleSize <= allowedSize)
{
super.insertString(fb, offs, str, a);
handleAutoTab(possibleSize, allowedSize, fb);
}
else
{
Toolkit.getDefaultToolkit().beep();
}
}
/**
* Make sure the replacement of text will not cause the Document to exceed
* its size limit. Also, potentially tab to next component when full.
*/
@Override
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
throws BadLocationException
{
int possibleSize = fb.getDocument().getLength() + str.length() - length;
int allowedSize = getAllowedSize( fb );
if (possibleSize <= allowedSize)
{
super.replace(fb, offs, length, str, a);
handleAutoTab(possibleSize, allowedSize, fb);
}
else
{
Toolkit.getDefaultToolkit().beep();
}
}
/**
* When a size isn't specified then we assume the desired size can be
* obtained from the associated text field. Otherwise, use the class
* size property.
*/
private int getAllowedSize(FilterBypass fb)
{
return (size == 0) ? getColumns(fb) : size;
}
/*
* Use the value returnd by invoking the getColumns() method of JTextField
*/
private int getColumns(FilterBypass fb)
{
// Find the text field that currently has focus
// and make sure it is using the Document that will be updated
Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (c != null && c instanceof JTextField)
{
JTextField textField = (JTextField)c;
Document doc = textField.getDocument();
if (doc.equals( fb.getDocument() ))
{
return textField.getColumns();
}
}
return 0;
}
/*
* When the Document is full tab to the next component.
*/
protected void handleAutoTab(int possibleSize, int allowedSize, FilterBypass fb)
{
if (autoTab == false
|| possibleSize != allowedSize)
return;
// Find the text field that currently has focus
// and make sure it is using the Document that has been updated
Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (c != null && c instanceof JTextComponent)
{
JTextComponent component = (JTextComponent)c;
Document doc = component.getDocument();
if (doc.equals( fb.getDocument() ))
{
c.transferFocus();
}
}
}
}
要使用它,您可以执行以下操作:
TabDocumentFilter tf = new TabDocumentFilter();
tf.installFilter( textField1, textField2 );
每个文本字段的字符将根据为文本字段指定的列数进行限制,并且会发生自动标签。
上述解决方案基于Text Field Auto Tab中提出的解决方案,该解决方案提供了嵌套DocumentFilters的方法。