从内部类引用 [英] Referencing from an inner class

查看:31
本文介绍了从内部类引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码

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();
    }
}

我的目标是创建一个 JTextField 数组,其中有一个键侦听器.此密钥侦听器应防止在 JTextField 中输入数字以外的任何内容.如果输入的数字不是整数,它还应该更改 JTextField 背景的颜色.例如 2147483647554.但是,当我编译这个时,我收到错误

My aim here is to create an array of JTextFields which have a keylistener on. This keylistener should prevent anything other than numbers being entered in the JTextField. It should also change the color of the JTextField's background if the number entered is not an int. For example 2147483647554. However when I compile this I get the error

那么我该如何制作才能使其在所有 JTextField 上都是最终的或有效的最终结果?

So how do I make this so that it is either final or effectively final on all the JTextFields?

推荐答案

我的目标是创建一个 JTextField 数组,其中有一个键侦听器.此密钥侦听器应防止在 JTextField 中输入数字以外的任何内容

My aim here is to create an array of JTextFields which have a keylistener on. This keylistener should prevent anything other than numbers being entered in the JTextField

对此的简短回答是,不要使用 KeyListener,它不会捕获用户将文本粘贴到字段中或以编程方式更新字段的用例

The short answer to this is, don't use KeyListener, it won't capture the use cases of the user pasting text into the field or if the field is updated programmatically

相反,您想使用 DocumentFilter,例如

Instead you want to use a DocumentFilter, for example

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);
    }
}

请参阅实施文档过滤器了解更多信息详细信息和 DocumentFilter 示例 了解更多示例

See Implementing a Document Filter for more details and DocumentFilter Examples for more examples

如果输入的数字不是整数,它也应该改变 JTextField 的背景颜色

It should also change the color of the JTextField's background if the number entered is not an int

您可以使用 InputVerifier 进行后期验证,但这可能无法满足您的需求.

You can do post validation using a InputVerifier, but that might not meet your needs.

这就产生了一个问题.DocumentFilter 不应该关心它应用到的字段,但是因为它正在执行验证,所以它会知道什么时候出了问题,所以我们需要某种方式让过滤器在什么时候提供通知验证失败...

This creates a problem. The DocumentFilter, shouldn't care about the field it's applied to, but since, it's doing the validation, it will know when something has gone wrong, so we need some way for the filter to provide notification when the validation fails...

首先,我们需要一些回调来告诉我们验证何时失败或通过...

First, we need some callback which tells us when validation has failed or passed...

public interface ValidationListener {

    public void validationFailed();

    public void validationPassed();
}

然后我们需要更新过滤器以根据其规则发出这些通知...

Then we need to update the filter to raise those notifications based on it's rules...

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 实现来执行我们需要的操作...

Then we need to define our implementation of the ValidationListener to perform the actions we need...

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"));
    }

}

这里,监听器维护一个对我们想要控制的字段的引用

Here, the listener maintains a reference to the field which we want to control

然后我们将其完全绑定...

Then we bind it altogether...

JTextField field = new JTextField(10);
DefaultValidationHandler handler = new DefaultValidationHandler(field);
IntFilter filter = new IntFilter();
filter.setValidationListener(handler);
((AbstractDocument)field.getDocument()).setDocumentFilter(filter);

这有点粗糙,但它可以理解基本概念.

This is all a bit crude, but it gets the basic idea across.

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

Some improvements might include passing the reference of the DocumentFilter back via the methods of the ValidationListener, you could then use this to lookup the field which triggered the event and update it, reducing the number of handlers you might need to create, for example.

例如

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);
        }

    }

}

这篇关于从内部类引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆