从内部类引用

时间:2015-06-18 06:31:58

标签: java arrays swing keylistener miglayout

我有以下代码

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。 但是当我编译它时,我得到了错误

Inner class error

那么我该如何做到这一点使它在所有JTextField上都是最终的或有效的最终版?

2 个答案:

答案 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);

Filter

这有点粗糙,但它得到了基本的想法。

一些改进可能包括通过DocumentFilter的方法传递ValidationListener的引用,然后您可以使用它来查找触发事件并更新它的字段,减少数量例如,您可能需要创建的处理程序。

例如

更新了ValidationListener

public interface ValidationListener {

    public void validationFailed(DocumentFilter filter);

    public void validationPassed(DocumentFilter filter);
}

更新了IntFilter

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最终

因此,一个快速解决方法是使用JFrameJPanel

在类范围内声明我
JFrame myMainWindow = new JFrame("Sorts");

JPanel sortPanel = new JPanel();
int i; 

然后在任何地方使用

 for(i = 0; i<nextTextBox;i++)