抽象输入验证器和JDialog类

时间:2017-05-02 16:05:03

标签: java swing

我试图理解我遇到的一个类here来验证我所拥有的几个JTextAreas的输入。我的工作正常,但我对某些逻辑感到困惑,特别提到使用JDialog作为父组件,并希望有人能帮助我更好地理解它。

Abstract validator类:

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的代码然后调用接口方法,看起来它在第一次调用verify()时被用来操作其他组件(通过java),然后是实现的方法&#39 ; validationCriteria()'

但事实上它是一个令我困惑的JDialog,为什么它不仅仅是一个JComponent?我想我在这里缺少一些基础知识 - 这就是为什么我对具体课程的实例只使用了一个新的' JDialog - 虽然我将要阅读inputverifier上的oracle路径,因为我认为这个类设计中的一些可能有点矫枉过正....

1 个答案:

答案 0 :(得分:2)

  

如上所述,我对JDialog的使用更加困惑。从上面链接中的描述,以及使用instanceof的代码然后调用接口方法,看起来它在第一次调用verify()时被用来操作其他组件(通过java),然后是实现的方法'validationCriteria( )”

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

根据示例代码,我会说他们只是在作弊,虽然我没有对其进行测试,但您可以通过null(但您必须将其转换为JDialogJFrame

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

进入细节,validationCriteria是您为组件提供验证的地方,正如您所描述的那样,verify调用了它。这提供了一种方法,通过该方法,作者可以控制验证过程并实现其自定义。请注意,c是对您要验证的JComponent的引用(即JTextArea

作者以WantsValidationStatus的形式提供了其他自定义功能,可以由parentJDialogJFrame)实施,该true提供了有关验证过程的状态

  

首先(但不重要)我很困惑为什么作者在抽象类中分离了构造函数?我不认为这特别重要。

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

  

但事实上,它是一个令我困惑的JDialog,为什么它不只是一个JComponent?我想我在这里缺少一些基础知识 - 这就是为什么我的具体类实例化只使用'新'JDialog - 虽然我将在inputverifier上读取oracle路径,因为我认为这个类设计中的一些可能是有点矫枉过正....

嗯,其他两条评论应该已经回答了现在:P

分手的想法

在我看来,这有点不对劲。我没有通过构造函数传递给类的任何组件,显示消息或采取其他操作不是它的责任,它的工作就是验证组件并返回false / InputVerifier(然后控制焦点横向。)

在我看来,validationFailed最好支持一个观察者模式,然后生成validationPassed / filter.setStopwordsHandler(new RegExStopwords("([^\\u1F600-\\u1F6FF\\s].*|[A-Za-z0-9].*|[٠-٩].*|[\\u0617-\\u061A\\u064B-\\u0652].*|[ؐ-ًؚٟ].*|[/(آ|إ|أ)/g, 'ا']|[/(ة)/g, 'ه']|[/(ئ|ؤ)/g, 'ء']|[/(ى)/g, 'ي']|[/([^\\u0621-\\u063A\\u0641-\\u064A\\u0660-\\u0669])/g, '']"));(或类似)事件并让其他一些委托制作关于应该做什么的决定,但那是;)