Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
147 views
in Technique[技术] by (71.8m points)

java - Drawing warning symbol during form validation in Swing

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.

Here is the code :-

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 :

enter image description here

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).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

enter image description here

like so:

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

see here for more.

UPDATE:

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

Some suggestions:

  • Dont extend JFrame unnecessarily

  • 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.

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

  • 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

  • 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:

enter image description here

And removes it when is corrected:

enter image description here

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...