在Swing中的表单验证期间绘制警告符号

Ins*_*der 2 java swing background jtextfield

我已经开发了一个swing表单来验证条目,因为焦点从JTextComponent中丢失,如果条目正确,则背景被涂成绿色,否则它被涂成红色.

这是代码: -

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;



public class Form extends JFrame implements FocusListener{
JTextField fname,lname,phone,email,address;
BufferedImage img;
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable(){public void run(){new Form();}});
}

public Form()
{
super("Form with Validation Capability");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,300);
setLayout(new GridLayout(5,3));

try {
    img=ImageIO.read(new File("src/warning.png"));
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

add(new JLabel("First Name :"));
add(fname=new JTextField(20));
add(new JLabel("Last Name :"));
add(lname=new JTextField(20));
add(new JLabel("Phone Number :"));
add(phone=new JTextField(10));
add(new JLabel("Email:"));
add(email=new JTextField(20));
add(new JLabel("Address :"));
add(address=new JTextField(20));

fname.addFocusListener(this);
lname.addFocusListener(this);
phone.addFocusListener(this);
email.addFocusListener(this);
address.addFocusListener(this);

setVisible(true);
}

public void focusGained(FocusEvent e)
{
((JTextComponent) e.getSource()).setBackground(Color.WHITE);
}
public void focusLost(FocusEvent e)
{
if(e.getSource().equals(fname))
{
    validationForText(fname);
}
else if(e.getSource().equals(lname))
{
    validationForText(lname);
}
else if(e.getSource().equals(email))
{
    validationForEmail(email);
}
else if(e.getSource().equals(phone))
{
    validationForNumber(phone);
}
else{
    ((JTextComponent) e.getSource()).setBackground(Color.GREEN);
}
}
public void validationForText(JTextComponent comp)
{
String temp=comp.getText();
if (temp.matches("^[A-Za-z]+$")) {
    comp.setBackground(Color.GREEN);
}
else
    comp.setBackground(Color.RED);
}
public void validationForNumber(JTextComponent comp)
{
String text=comp.getText();
if(text.matches("^[0-9]+$"))
    comp.setBackground(Color.GREEN);
else
    comp.setBackground(Color.RED);
}
public void validationForEmail(JTextComponent comp)
{
String text=comp.getText();
if(text.matches("[^@]+@([^.]+\\.)+[^.]+"))
    comp.setBackground(Color.GREEN);
else
    comp.setBackground(Color.RED);
}

}
Run Code Online (Sandbox Code Playgroud)

这是我的简单应用程序的输出:

在此输入图像描述

现在我还想在错误字段的左下角绘制一个警告符号(缓冲图像).任何人都可以帮我解决这个问题,因为我不知道在哪里画图像.(我想使用JLayeredPane,因为我正在学习它的应用程序,任何代码片段都会有帮助).

Dav*_*amp 8

为什么不简单地JLabel使用LayoutManager内置的Swing警告图标添加(使用适当的位置)UIManager.getIcon("OptionPane.warningIcon")

在此输入图像描述

像这样:

JLabel label=new JLabel(UIManager.getIcon("OptionPane.warningIcon"));
Run Code Online (Sandbox Code Playgroud)

请看这里了解更多.

更新:

根据你的评论,我宁愿使用GlassPane(并添加JLabel到glasspane),相反也是如此JLayeredPane.见这里更多关于RootPanes

一些建议:

  • 不要JFrame不必要地扩展

  • 不要叫setSizeJFrame.必要时使用正确LayoutManager和/或覆盖getPreferredSize(),并设置可见之前替换setSize呼叫.pack() JFrame

  • FocusListener除非您想与其他类共享功能,否则不要在类上实现.

  • 也养成了使用FocusAdaptervs 的习惯,FocusListener这适用于一些附加的Listener,即MouseListener可以替换为MouseAdapter.这允许我们只覆盖我们想要的方法.在这种情况下,监听器是正确的,因为我们对两种重写方法都做了一些事情,但正如我对这个习惯所说的更多

  • 也总是调用super.XXX重写方法的实现,即focusGained(FocusEvent fe)除非你因为某个原因而忽略它

以下是包含以上修复的代码,包括glasspane,当字段为红色时显示警告图标:

在此输入图像描述

并在纠正后将其删除:

在此输入图像描述

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.JTextComponent;

/**
 *
 * @author David
 */
public class GlassValidationPane extends JComponent {

    private static JTextField fname, lname, phone, email, address;
    private static GlassValidationPane gvp = new GlassValidationPane();

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {

                JFrame f = new JFrame("Form with Validation Capability");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                //f.setResizable(false);
                f.setLayout(new GridLayout(5, 3));

                f.add(new JLabel("First Name :"));
                f.add(fname = new JTextField(20));
                f.add(new JLabel("Last Name :"));
                f.add(lname = new JTextField(20));
                f.add(new JLabel("Phone Number :"));
                f.add(phone = new JTextField(10));
                f.add(new JLabel("Email:"));
                f.add(email = new JTextField(20));
                f.add(new JLabel("Address :"));
                f.add(address = new JTextField(20));

                f.addComponentListener(new ComponentAdapter() {
                    @Override
                    public void componentResized(ComponentEvent ce) {
                        super.componentResized(ce);
                        gvp.refreshLocations();
                    }
                });
                FocusAdapter fl = new FocusAdapter() {
                    @Override
                    public void focusGained(FocusEvent fe) {
                        super.focusGained(fe);
                        ((JTextComponent) fe.getSource()).setBackground(Color.WHITE);
                    }

                    @Override
                    public void focusLost(FocusEvent fe) {
                        super.focusLost(fe);
                        if (fe.getSource().equals(fname)) {
                            validationForText(fname);
                        } else if (fe.getSource().equals(lname)) {
                            validationForText(lname);
                        } else if (fe.getSource().equals(email)) {
                            validationForEmail(email);
                        } else if (fe.getSource().equals(phone)) {
                            validationForNumber(phone);
                        } else {
                            gvp.removeWarningIcon(((Component) fe.getSource()));
                            ((JTextComponent) fe.getSource()).setBackground(Color.GREEN);
                        }
                    }
                };

                fname.addFocusListener(fl);
                lname.addFocusListener(fl);
                phone.addFocusListener(fl);
                email.addFocusListener(fl);
                address.addFocusListener(fl);

                f.setGlassPane(gvp);

                f.pack();
                f.setVisible(true);
                gvp.setVisible(true);
            }

            public void validationForText(JTextComponent comp) {
                String temp = comp.getText();
                if (temp.matches("^[A-Za-z]+$")) {
                    setGreen(comp);
                } else {
                    setRed(comp);
                }
            }

            public void validationForNumber(JTextComponent comp) {
                String text = comp.getText();
                if (text.matches("^[0-9]+$")) {
                    setGreen(comp);
                } else {
                    setRed(comp);
                }
            }

            public void validationForEmail(JTextComponent comp) {
                String text = comp.getText();
                if (text.matches("[^@]+@([^.]+\\.)+[^.]+")) {
                    setGreen(comp);
                } else {
                    setRed(comp);
                }
            }

            private void setRed(JTextComponent comp) {
                comp.setBackground(Color.RED);
                gvp.showWarningIcon(comp);
            }

            private void setGreen(JTextComponent comp) {
                comp.setBackground(Color.GREEN);
                gvp.removeWarningIcon(comp);

            }
        });
    }
    private HashMap<Component, JLabel> warningLabels = new HashMap<>();
    private ImageIcon warningIcon;

    public GlassValidationPane() {
        setLayout(null);//this is the exception to the rule case a layoutmanager might make setting Jlabel co-ords harder
        setOpaque(false);
        Icon icon = UIManager.getIcon("OptionPane.warningIcon");
        int imgW = icon.getIconWidth();
        int imgH = icon.getIconHeight();
        BufferedImage img = ImageUtilities.getBufferedImageOfIcon(icon, imgW, imgH);
        warningIcon = new ImageIcon(ImageUtilities.resize(img, 24, 24));
    }

    void showWarningIcon(Component c) {
        if (warningLabels.containsKey(c)) {
            return;
        }

        JLabel label = new JLabel();
        label.setIcon(warningIcon);

        //int x=c.getX();//this will make it insode the component
        int x = c.getWidth() - label.getIcon().getIconWidth();//this makes it appear outside/next to component
        int y = c.getY();

        label.setBounds(x, y, label.getIcon().getIconWidth(), label.getIcon().getIconHeight());
        add(label);
        label.setVisible(true);
        revalidate();
        repaint();
        warningLabels.put(c, label);
    }

    public void removeWarningIcon(Component c) {
        for (Map.Entry<Component, JLabel> entry : warningLabels.entrySet()) {
            Component component = entry.getKey();
            JLabel jLabel = entry.getValue();
            if (component == c) {
                remove(jLabel);
                revalidate();
                repaint();
                break;
            }
        }
        warningLabels.remove(c);
    }

    public void refreshLocations() {
        for (Map.Entry<Component, JLabel> entry : warningLabels.entrySet()) {
            Component c = entry.getKey();
            JLabel label = entry.getValue();
            //int x=c.getX();//this will make it insode the component
            int x = c.getWidth() - label.getIcon().getIconWidth();//this makes it appear outside/next to component
            int y = c.getY();

            label.setBounds(x, y, label.getIcon().getIconWidth(), label.getIcon().getIconHeight());
            revalidate();
            repaint();
        }
    }
}

class ImageUtilities {

    public static BufferedImage resize(BufferedImage image, int width, int height) {
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
        Graphics2D g2d = (Graphics2D) bi.createGraphics();
        g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
        g2d.drawImage(image, 0, 0, width, height, null);
        g2d.dispose();
        return bi;
    }

    public static BufferedImage getBufferedImageOfIcon(Icon icon, int imgW, int imgH) {
        BufferedImage img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D) img.getGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        icon.paintIcon(null, g2d, 0, 0);
        g2d.dispose();
        return img;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • "图标"为+1.还要考虑在`InputVerifier`的`shouldYieldFocus()`方法中这样做,这里提到[这里](http://stackoverflow.com/a/14170275/230513). (3认同)
  • @naveen你可能会看一下[使用JXLayer验证覆盖](http://www.pushing-pixels.org/2007/08/01/validation-overlays-using-jxlayer.html)和[Validaion覆盖使用玻璃窗格](http://www.pushing-pixels.org/2007/08/02/validation-overlays-using-glass-pane.html) - nb JXLayer应该可以由Java 7上的JLayer替换 (2认同)