Java 抽象输入验证器和JDialog类

Java 抽象输入验证器和JDialog类,java,swing,Java,Swing,我试图理解我遇到的一个类,它验证了我在一些jtext领域的输入。我已经让它很好地工作了,但是我对其中的一些逻辑感到困惑,特别提到了使用JDialog作为父组件,希望有人能帮助我更好地理解它 抽象验证器类: package gui; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Point; import java.awt.event.KeyEvent;

我试图理解我遇到的一个类,它验证了我在一些jtext领域的输入。我已经让它很好地工作了,但是我对其中的一些逻辑感到困惑,特别提到了使用JDialog作为父组件,希望有人能帮助我更好地理解它

抽象验证器类:

package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.BorderFactory;
import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.border.BevelBorder;

public abstract class AbstractValidator extends InputVerifier implements KeyListener{

private JDialog popup;
private Object parent;
private JLabel messageLabel;
private JLabel image;
private Point point;
private Dimension cDim;
private Color color;

private AbstractValidator(){
    color = new Color(243,255,159);
}

private AbstractValidator(JComponent c, String msg){
    this();
    c.addKeyListener(this);
    messageLabel = new JLabel(msg + " ");
    //image = new JLabel();         
}

public AbstractValidator(JDialog parent, JComponent c, String msg){
    this(c,msg);
    this.parent = parent;
    popup = new JDialog(parent);
    initComponents();
}

//implement the actual validation logic, returning false if the data is 
//invalid and true if it is not. you can also set the popup msg text with
//setMessage() before returning.
//param c is the component to be validated

protected abstract boolean validationCriteria(JComponent c);

//this method is called by Java when a component needs to be validated. 
//it should not be called directly. Don't override this unless you want to change
//validation behaviour. implement validationCriteria() instead.

@Override
public boolean verify(JComponent c){
    if(!validationCriteria(c)){
        if(parent instanceof Validatable)
            ((Validatable)parent).validateFailed();

        c.setBorder(BorderFactory.createLineBorder(Color.RED));
        popup.setSize(0,0);
        popup.setLocationRelativeTo(c);
        point = popup.getLocation();
        cDim = c.getSize();
        popup.setLocation(point.x-(int)cDim.getWidth()/2, point.y+(int)cDim.getHeight()/2);
        popup.pack();
        popup.setVisible(true);
        return false;
    }
    c.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
    if(parent instanceof Validatable)
        ((Validatable)parent).validatePassed();
    return true;
}

protected void setMessage(String msg){
    messageLabel.setText(msg);   
}

@Override
public void keyPressed(KeyEvent e){
    popup.setVisible(false);
}

@Override
public void keyTyped(KeyEvent e){
}
@Override
public void keyReleased(KeyEvent e){}

private void initComponents(){
    popup.getContentPane().setLayout(new FlowLayout());
    popup.setUndecorated(true);
    popup.getContentPane().setBackground(color);
    popup.getContentPane().add(messageLabel);
    popup.setFocusableWindowState(false);

}
}
混凝土等级:

package gui;

import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JTextField;

public class NotEmptyValidator extends AbstractValidator{
    public NotEmptyValidator(JDialog parent, JTextField c, String msg){
        super(parent,c, msg);
    }

    protected boolean validationCriteria(JComponent c){
        if(((JTextField)c).getText().equals("")){
            return false;
        }
        return true;
    }
}
(未使用的)接口:

package gui;

public interface Validatable {
    void validateFailed();
    void validatePassed();
}
在主JPanel中的JTextField上使用混凝土类:

textField.setInputVerifier(new NotEmptyValidator(new JDialog(), textField, "msg"));    
首先(但不重要的是),我对作者为什么在抽象类中分离构造函数感到困惑?但我认为这并不特别重要

不过,正如前面提到的,我对JDialog思想的使用感到更加困惑。 从上面链接中的描述,以及使用instanceof然后调用接口方法的代码来看,它看起来像是在第一次(由java)调用verify()之后再调用实现的方法“validationCriteria()”时用来操作其他组件

但这是一个让我困惑的JDialog,为什么它不只是一个JComponent呢?我想我在这里缺少一些基础知识——这就是为什么我的具体类实例化只使用了一个“新的”JDialog——尽管我将在inputverifier上阅读oracle trail,因为我认为这个类的一些设计可能也有点过火了

不过,正如前面提到的,我对JDialog思想的使用感到更加困惑。从上面链接中的描述,以及使用instanceof然后调用接口方法的代码来看,它看起来像是在第一次(由java)调用verify()之后再调用实现的方法“validationCriteria()”时用来操作其他组件

他们似乎使用
JDialog
(或
JFrame
)作为自己内部
JDialog
的参考点,在验证失败时用于显示消息。这是
JDialog
的一个(可选)要求,它允许将它放置在调用它的父窗口上

根据示例代码,我认为他们只是在作弊,虽然我没有测试它,但您可以通过
null
(但您必须将其转换为
JDialog
JFrame

也可能有点旧(或者他们不知道一些附加的API功能),因为他们可以使用
setLocationRelativeTo
而不是手动定位对话框

深入本质,
validationCriteria
是您为组件提供验证的地方,正如您所描述的,这被称为
verify
。这提供了作者控制验证过程并实现其定制的方法。请记住,
c
是对您试图验证的
JComponent
的引用(即
JTextArea

作者以
WantsValidationStatus
的形式提供了额外的定制,可由
父级
JDialog
JFrame
)实现,它提供了一种关于验证过程状态的通知方式

首先(但不重要的是),我对作者为什么在抽象类中分离构造函数感到困惑?但我认为这并不特别重要

我的猜测是,他们希望提供灵活的安排,但不理解Swing API提供的一些特性,例如。您可以将构造函数的数量减少到1,并使用来获取对包含该组件的窗口的引用

但这是一个让我困惑的JDialog,为什么它不只是一个JComponent呢?我想我在这里缺少一些基础知识——这就是为什么我的具体类实例化只使用了一个“新的”JDialog——尽管我将在inputverifier上阅读oracle trail,因为我认为这个类的一些设计可能也有点过火了

好吧,其他两条评论现在应该已经回答了这个问题:p

离别的想法 在我看来,这有点错误。我不会让任何组件通过构造函数传递给类,显示消息或执行其他操作不是它的责任,它的工作只是验证组件并返回
true
/
false
(然后控制焦点横向)

在我看来,
InputVerifier
最好支持观察者模式,然后生成
validationFailed
/
validationPassed
(或类似)事件,并让其他代表决定应该做什么,但这是;)

不过,正如前面提到的,我对JDialog思想的使用感到更加困惑。从上面链接中的描述,以及使用instanceof然后调用接口方法的代码来看,它看起来像是在第一次(由java)调用verify()之后再调用实现的方法“validationCriteria()”时用来操作其他组件

他们似乎使用
JDialog
(或
JFrame
)作为自己内部
JDialog
的参考点,在验证失败时用于显示消息。这是
JDialog
的一个(可选)要求,它允许将它放置在调用它的父窗口上

根据示例代码,我认为他们只是在作弊,虽然我没有测试它,但您可以通过
null
(但您必须将其转换为
JDialog
JFrame

也可能有点旧(或者他们不知道一些附加的API功能),因为他们可以使用
setLocationRelativeTo
而不是手动定位对话框

深入本质,
validationCriteria
是为组件提供验证的地方,