JTextField 覆盖选中时自动删除字符
JTextField to remove characters automatically when overwritting selected
我正在使用 Java,我有一个只能有 4 位数字的 JTextField。我正在使用扩展 DocumentFilter 的 class 来过滤掉任何其他字符,并将字符数限制为 4。
问题是,一旦我有 4 位数字,如果我 select 所有这些数字并尝试通过输入另一个数字来覆盖它们,它不会自动覆盖并且什么都不做,我必须 显式 在我的键盘中输入 "Backspace" 或 "Delete" 以删除 4 位数字,然后(一旦该字段被清除)我可以再次输入。
如何让 JTextField 充当操作系统的其余部分,一旦我有一些文本 selected 如果我键入一个字符,它“删除所有字符,然后写入字符”(它 替代内容)。
我有一个辅助 class, JustLimitDigitFilter.java
:
import javax.swing.text.DocumentFilter;
import javax.swing.text.BadLocationException;
import java.awt.Toolkit;
import javax.swing.text.AttributeSet;
public class JustLimitDigitFilter extends DocumentFilter {
int limit;
public JustLimitDigitFilter(int limit) {
this.limit = limit;
}
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
// if (text == null) {
// return;
// }
String str = text.replaceAll("\D", "");
if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
super.insertString(fb, offset, str, attr);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attr)
throws BadLocationException {
// if (text == null) {
// return;
// }
String str = text.replaceAll("\D", "");
if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
super.replace(fb, offset, length, str, attr);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
}
和主要的 class, App.java
:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.DocumentFilter;
public class App {
private JFrame frame;
private JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
App window = new App();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public App() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 191, 96);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JPanel panel = new JPanel();
panel.setBounds(6, 6, 179, 62);
frame.getContentPane().add(panel);
panel.setLayout(null);
textField = new JTextField();
textField.setBounds(6, 6, 167, 26);
panel.add(textField);
textField.setColumns(10);
// without this code below this, the textfield is “normal” when
// something is selected if I write it overwrites the selection
AbstractDocument doc = (AbstractDocument) textField.getDocument();
doc.setDocumentFilter(new JustLimitDigitFilter(4));
}
}
欢迎任何建议,因为我是新手,除了我明确表示的疑问。
classDocumentFilter
中的方法replace()
实际上执行了两个操作。首先,它删除从 offset
开始的 length
个字符,然后在 offset
处插入 text
个字符。因此,当 JTextField
包含最大允许字符数时,replace()
方法中的以下行不会发生任何事情...
if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
如果JTextField
已满,那么它的长度将是最大字符数,所以加上str
的长度将总是更大比 limit
.
扩展 Abra 的回答:
replace(...)
方法中的 "length" 参数包含要删除的字符数。
因此您可以将 if 语句更改为:
//if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit)
if (!str.isEmpty() && (fb.getDocument().getLength() + str.length() - length) <= limit)
进行此更改后,您可以将 insert(...)
方法简化为:
@Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributes)
throws BadLocationException
{
replace(fb, offset, 0, text, attributes);
}
我正在使用 Java,我有一个只能有 4 位数字的 JTextField。我正在使用扩展 DocumentFilter 的 class 来过滤掉任何其他字符,并将字符数限制为 4。
问题是,一旦我有 4 位数字,如果我 select 所有这些数字并尝试通过输入另一个数字来覆盖它们,它不会自动覆盖并且什么都不做,我必须 显式 在我的键盘中输入 "Backspace" 或 "Delete" 以删除 4 位数字,然后(一旦该字段被清除)我可以再次输入。
如何让 JTextField 充当操作系统的其余部分,一旦我有一些文本 selected 如果我键入一个字符,它“删除所有字符,然后写入字符”(它 替代内容)。
我有一个辅助 class, JustLimitDigitFilter.java
:
import javax.swing.text.DocumentFilter;
import javax.swing.text.BadLocationException;
import java.awt.Toolkit;
import javax.swing.text.AttributeSet;
public class JustLimitDigitFilter extends DocumentFilter {
int limit;
public JustLimitDigitFilter(int limit) {
this.limit = limit;
}
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
// if (text == null) {
// return;
// }
String str = text.replaceAll("\D", "");
if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
super.insertString(fb, offset, str, attr);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attr)
throws BadLocationException {
// if (text == null) {
// return;
// }
String str = text.replaceAll("\D", "");
if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
super.replace(fb, offset, length, str, attr);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
}
和主要的 class, App.java
:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.DocumentFilter;
public class App {
private JFrame frame;
private JTextField textField;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
App window = new App();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public App() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 191, 96);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JPanel panel = new JPanel();
panel.setBounds(6, 6, 179, 62);
frame.getContentPane().add(panel);
panel.setLayout(null);
textField = new JTextField();
textField.setBounds(6, 6, 167, 26);
panel.add(textField);
textField.setColumns(10);
// without this code below this, the textfield is “normal” when
// something is selected if I write it overwrites the selection
AbstractDocument doc = (AbstractDocument) textField.getDocument();
doc.setDocumentFilter(new JustLimitDigitFilter(4));
}
}
欢迎任何建议,因为我是新手,除了我明确表示的疑问。
classDocumentFilter
中的方法replace()
实际上执行了两个操作。首先,它删除从 offset
开始的 length
个字符,然后在 offset
处插入 text
个字符。因此,当 JTextField
包含最大允许字符数时,replace()
方法中的以下行不会发生任何事情...
if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
如果JTextField
已满,那么它的长度将是最大字符数,所以加上str
的长度将总是更大比 limit
.
扩展 Abra 的回答:
replace(...)
方法中的 "length" 参数包含要删除的字符数。
因此您可以将 if 语句更改为:
//if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit)
if (!str.isEmpty() && (fb.getDocument().getLength() + str.length() - length) <= limit)
进行此更改后,您可以将 insert(...)
方法简化为:
@Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributes)
throws BadLocationException
{
replace(fb, offset, 0, text, attributes);
}