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

我开发了一个swing表单,用于validation条目,因为焦点从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); } } 

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

在此处输入图像描述

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

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

在此处输入图像描述

像这样:

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

看到这里了解更多。

更新:

根据你的评论,我宁愿使用GlassPane (并将JLabel添加到glasspane),而不是JLayeredPane 。 有关RootPanes更多信息,请参见此处

一些建议:

  • 不要不必要地扩展JFrame

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

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

  • 另外养成使用FocusAdapterFocusListener的习惯,这适用于附加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 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 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 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; } }