我有以下代码
import javax.swing.*;
import java.awt.*;
import net.miginfocom.swing.MigLayout;
import Sorts.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.Color;
public class SortsGui
{
JFrame myMainWindow = new JFrame("Sorts");
JPanel sortPanel = new JPanel();
//first panel components
public int nextTextBox = 20;
JTextField[] allField = new JTextField [25];
//end first panel
public void runGUI()
{
myMainWindow.setBounds(10, 10, 800, 800);
myMainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myMainWindow.setLayout(new GridLayout(1,1));
createSortTestPanel();
myMainWindow.getContentPane().add(sortPanel);
myMainWindow.setVisible(true);
}
public void createSortTestPanel()
{
MigLayout layout = new MigLayout("" , "[grow]");
sortPanel.setLayout(layout);
refreshScreen();
}
public void refreshScreen()
{
sortPanel.removeAll();
for(int i = 0; i<nextTextBox;i++)
{
int fix = i+1;
allField[i] = new JTextField("");
sortPanel.add(allField[i],"growx");
allField[i].addKeyListener(new KeyListener ()
{
public void keyPressed(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
char c = e.getKeyChar();
if(Character.isDigit(c))
{
}
else
{
e.consume();
}
try
{
int parseTest = Integer.parseInt(allField[i].getText());
}
catch(Exception exc)
{
allField[i].setBackground(Color.RED);
}
}
});
}
}
public static void main(String[] args)
{
SortsGui sG = new SortsGui();
sG.runGUI();
}
}
我的目标是创建一个具有keylistener的JTextField数组。此keylistener应该防止在JTextField中输入数字以外的任何内容。如果输入的数字不是int,它还应该更改JTextField背景的颜色。例如2147483647554。 但是当我编译它时,我得到了错误
那么我该如何做到这一点使它在所有JTextField上都是最终的或有效的最终版?
答案 0 :(得分:4)
我的目标是创建一个具有keylistener的JTextField数组。此keylistener应该防止在JTextField中输入数字以外的任何内容
简而言之,不要使用KeyListener
,它不会捕获用户将文本粘贴到字段中的用例,或者是否以编程方式更新字段
相反,您想要使用DocumentFilter
,例如
public class IntFilter extends DocumentFilter {
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
StringBuilder buffer = new StringBuilder(text.length());
for (int index = 0; index < text.length(); index++) {
if (Character.isDigit(text.charAt(index))) {
buffer.append(text.charAt(index));
}
}
super.insertString(fb, offset, buffer.toString(), attr);
ValidationListener listener = getValidationListener();
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException {
if (length > 0) {
fb.remove(offset, length);
}
insertString(fb, offset, string, attr);
}
}
有关详细信息,请参阅Implementing a Document Filter;有关更多示例,请参阅DocumentFilter Examples
如果输入的数字不是int,它也应该改变JTextField背景的颜色
您可以使用InputVerifier
进行发布验证,但这可能无法满足您的需求。
这会产生问题。 DocumentFilter
,不应该关心它应用的字段,但是因为它正在进行验证,它会知道什么时候出错了,所以我们需要一些方法让过滤器在验证失败时提供通知...
首先,我们需要一些回调,它告诉我们验证失败或通过时......
public interface ValidationListener {
public void validationFailed();
public void validationPassed();
}
然后我们需要更新过滤器以根据它的规则提出这些通知......
public class IntFilter extends DocumentFilter {
private ValidationListener validationListener;
public void setValidationListener(ValidationListener validationListener) {
this.validationListener = validationListener;
}
public ValidationListener getValidationListener() {
return validationListener;
}
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
boolean validationFailed = false;
StringBuilder buffer = new StringBuilder(text.length());
for (int index = 0; index < text.length(); index++) {
if (Character.isDigit(text.charAt(index))) {
buffer.append(text.charAt(index));
} else {
validationFailed = true;
}
}
super.insertString(fb, offset, buffer.toString(), attr);
ValidationListener listener = getValidationListener();
if (listener != null) {
if (validationFailed) {
listener.validationFailed();
} else {
listener.validationPassed();
}
}
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException {
if (length > 0) {
fb.remove(offset, length);
}
insertString(fb, offset, string, attr);
}
}
然后我们需要定义ValidationListener
的实现来执行我们需要的操作......
public class DefaultValidationHandler implements ValidationListener {
private JTextField field;
public DefaultValidationHandler(JTextField field) {
this.field = field;
}
public JTextField getField() {
return field;
}
@Override
public void validationFailed() {
getField().setBackground(Color.RED);
}
@Override
public void validationPassed() {
getField().setBackground(UIManager.getColor("TextField.background"));
}
}
这里,监听器维护对我们想要控制的字段的引用
然后我们完全绑定它......
JTextField field = new JTextField(10);
DefaultValidationHandler handler = new DefaultValidationHandler(field);
IntFilter filter = new IntFilter();
filter.setValidationListener(handler);
((AbstractDocument)field.getDocument()).setDocumentFilter(filter);
这有点粗糙,但它得到了基本的想法。
一些改进可能包括通过DocumentFilter
的方法传递ValidationListener
的引用,然后您可以使用它来查找触发事件并更新它的字段,减少数量例如,您可能需要创建的处理程序。
例如
public interface ValidationListener {
public void validationFailed(DocumentFilter filter);
public void validationPassed(DocumentFilter filter);
}
public class IntFilter extends DocumentFilter {
private ValidationListener validationListener;
public void setValidationListener(ValidationListener validationListener) {
this.validationListener = validationListener;
}
public ValidationListener getValidationListener() {
return validationListener;
}
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
boolean validationFailed = false;
StringBuilder buffer = new StringBuilder(text.length());
for (int index = 0; index < text.length(); index++) {
if (Character.isDigit(text.charAt(index))) {
buffer.append(text.charAt(index));
} else {
validationFailed = true;
}
}
super.insertString(fb, offset, buffer.toString(), attr);
ValidationListener listener = getValidationListener();
if (listener != null) {
if (validationFailed) {
listener.validationFailed(this);
} else {
listener.validationPassed(this);
}
}
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException {
if (length > 0) {
fb.remove(offset, length);
}
insertString(fb, offset, string, attr);
}
}
public class TestPane extends JPanel {
private Map<DocumentFilter, JTextField> fields;
public TestPane() {
fields = new HashMap<>(25);
ValidationListener listener = new ValidationListener() {
@Override
public void validationFailed(DocumentFilter filter) {
JTextField field = fields.get(filter);
if (field != null) {
field.setBackground(Color.RED);
}
}
@Override
public void validationPassed(DocumentFilter filter) {
JTextField field = fields.get(filter);
if (field != null) {
field.setBackground(UIManager.getColor("TextField.background"));
}
}
};
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (int index = 0; index < 10; index++) {
JTextField field = new JTextField(10);
IntFilter filter = new IntFilter();
filter.setValidationListener(listener);
((AbstractDocument) field.getDocument()).setDocumentFilter(filter);
fields.put(filter, field);
add(field, gbc);
}
}
}
答案 1 :(得分:0)
您有一个范围问题,这就是导致此错误的原因:
for(int i = 0; i<nextTextBox;i++) //you are declaring i here
在KeyListener
内使用,这是禁止的。因为local
non-final
变量无法从内部类访问,所以它必须是最终的。在你的情况下,我认为不可能i
最终
因此,一个快速解决方法是使用JFrame
和JPanel
JFrame myMainWindow = new JFrame("Sorts");
JPanel sortPanel = new JPanel();
int i;
然后在任何地方使用
for(i = 0; i<nextTextBox;i++)