在 Swing 中的表单验证期间绘制警告符号 [英] Drawing warning symbol during form validation in Swing

查看:33
本文介绍了在 Swing 中的表单验证期间绘制警告符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了一个摆动表单,当焦点从 JTextComponent 丢失时验证条目如果输入正确,则背景为绿色,否则为红色.

I have developed a swing form which validates entries as the focus is lost from JTextComponent and if the entry is correct ,the background is painted green Otherwise it is painted red.

这里是代码:-

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

}

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

Here is the output to my simple app :

现在我还想在错误字段的左下角绘制一个警告符号(缓冲图像).谁能帮助我如何做到这一点,因为我不知道在哪里绘制图像.(我想使用 JLayeredPane 来完成它,因为我正在学习它的应用程序,任何代码片段都会有帮助).

Now I also want to draw a warning symbol (buffered image) at the lower left corner of incorrect field.Can anyone help me how to do this as i am not understanding where to paint the image. (I would like to do it using JLayeredPane as I am learning its application,any code snippet will really help).

推荐答案

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

Why not simply add a JLabel (using an appropriate LayoutManager to position it) with the inbuilt Swing warning icon UIManager.getIcon("OptionPane.warningIcon")

像这样:

JLabel label=new JLabel(UIManager.getIcon("OptionPane.warningIcon"));

请参阅此处了解更多.

更新:

根据您的评论,我宁愿使用 GlassPane(并将 JLabel 添加到 glasspane)而不是 JLayeredPane.请参阅这里了解更多关于RootPanes

As per your comment I would rather use GlassPane (and add JLabel to glasspane) for this as opposed too JLayeredPane. See here for more on RootPanes

一些建议:

  • 不要不必要地扩展 JFrame

不要在 JFrame 上调用 setSize.使用正确的 LayoutManager 和/或在必要时覆盖 getPreferredSize() 并将 setSize 调用替换为 pack() 就在设置 JFrame 可见之前.

Dont call setSize on JFrame. Use a correct LayoutManager and/or override getPreferredSize() where necessary and replace setSize call with pack() just before setting JFrame visible.

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

Dont implement FocusListener on the class unless you want to share the functionality with other classes.

还要养成使用FocusAdapter vs FocusListener的习惯,这适用于少数带有附加Listener的即MouseListener可以替换MouseAdapter.这允许我们只覆盖我们想要的方法.在这种情况下,侦听器是正确的,因为我们对两种重写方法都做了一些事情,但正如我所说的更多关于习惯的内容

Also get into the habit of using FocusAdapter vs FocusListener this applies to a few with appended Listener i.e MouseListener can be replaced for MouseAdapter. This allows us to only override the methods we want. In this case listener is correct as we do something on both overridden methods, but as I said more about the habit

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

Also always call super.XXX implementation of overridden methods i.e focusGained(FocusEvent fe) unless you are ignoring it for a reason

这是具有上述修复的代码,包括玻璃窗格以在字段为红色时显示警告图标:

Here is code with above fixes including glasspane to show warning icon when field is red:

并在纠正时将其删除:

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

这篇关于在 Swing 中的表单验证期间绘制警告符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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