当输入与我期望的用户不同时,我有一个类在 textField 后面设置警告图标。对于文本字段,此类工作完美,但是当我尝试将其与 textArea 一起使用时,警告图标未设置在正确的位置。
这是设置和删除警告图标的类:
public class GlassValidationPane extends JComponent {
private HashMap<Component, JLabel> warningLabels = new HashMap<>();
private ImageIcon warningIcon;
private final ImageUtilities iU = new ImageUtilities();
public GlassValidationPane() {
setLayout(null);
setOpaque(false);
Icon icon = UIManager.getIcon("OptionPane.warningIcon");
int imgW = icon.getIconWidth();
int imgH = icon.getIconHeight();
BufferedImage img = iU.getBufferedImageOfIcon(icon, imgW, imgH);
warningIcon = new ImageIcon(iU.resize(img, 18, 18));
}
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() + c.getX() + label.getIcon().getIconWidth();//this makes it appear outside/next to component);
int y = c.getY();
System.out.println("ïn show warning: " + y);
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.getWidth() + c.getX() + 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();
}
}
public boolean allSet(){
if(!warningLabels.isEmpty()){
JOptionPane.showMessageDialog(null, "Please fill every text field in, or adjust te wrong input", "Empty input/Wrong input", JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
private class ImageUtilities {
public 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 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;
}
}
}
我发现 textArea 的 getY() 函数总是返回 0,但我找不到为什么它总是返回 0。这是调用 ClaxxValidationPane 类的代码:
public class JobInput extends JFrame {
private JPanel contentPane;
private JTextField txtJobId;
private GlassValidationPane gvp;
private JTextArea textAreaDesription;
private boolean INSERT;
/**
* Create the frame.
*/
public JobInput(String titel, boolean INSERT) {
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
setBounds(100, 100, 296, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout();
gbl_contentPane.columnWidths = new int[]{0, 0, 0};
gbl_contentPane.rowHeights = new int[]{0, 0, 0, 0, 0, 0};
gbl_contentPane.columnWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
gbl_contentPane.rowWeights = new double[]{0.0, 0.0, 0.0, 1.0, 0.0, Double.MIN_VALUE};
contentPane.setLayout(gbl_contentPane);
JLabel lblTitel = new JLabel(titel);
lblTitel.setFont(new Font("Arial", Font.BOLD, 15));
GridBagConstraints gbc_lblTitel = new GridBagConstraints();
gbc_lblTitel.gridwidth = 2;
gbc_lblTitel.insets = new Insets(0, 0, 5, 0);
gbc_lblTitel.gridx = 0;
gbc_lblTitel.gridy = 0;
contentPane.add(lblTitel, gbc_lblTitel);
JSeparator separator = new JSeparator();
GridBagConstraints gbc_separator = new GridBagConstraints();
gbc_separator.fill = GridBagConstraints.BOTH;
gbc_separator.gridwidth = 2;
gbc_separator.insets = new Insets(0, 0, 5, 0);
gbc_separator.gridx = 0;
gbc_separator.gridy = 1;
contentPane.add(separator, gbc_separator);
JLabel lblJobid = new JLabel("JobID");
GridBagConstraints gbc_lblJobid = new GridBagConstraints();
gbc_lblJobid.anchor = GridBagConstraints.EAST;
gbc_lblJobid.insets = new Insets(0, 0, 5, 5);
gbc_lblJobid.gridx = 0;
gbc_lblJobid.gridy = 2;
contentPane.add(lblJobid, gbc_lblJobid);
txtJobId = new JTextField();
GridBagConstraints gbc_txtJobId = new GridBagConstraints();
gbc_txtJobId.insets = new Insets(0, 0, 5, 0);
gbc_txtJobId.fill = GridBagConstraints.HORIZONTAL;
gbc_txtJobId.gridx = 1;
gbc_txtJobId.gridy = 2;
contentPane.add(txtJobId, gbc_txtJobId);
txtJobId.setColumns(10);
JLabel lblDescription = new JLabel("Description");
GridBagConstraints gbc_lblDescription = new GridBagConstraints();
gbc_lblDescription.anchor = GridBagConstraints.NORTH;
gbc_lblDescription.insets = new Insets(0, 0, 5, 5);
gbc_lblDescription.gridx = 0;
gbc_lblDescription.gridy = 3;
contentPane.add(lblDescription, gbc_lblDescription);
textAreaDesription = new JTextArea();
textAreaDesription.setLineWrap(true);
textAreaDesription.setWrapStyleWord(true);
GridBagConstraints gbc_textArea = new GridBagConstraints();
gbc_textArea.insets = new Insets(0, 0, 5, 0);
gbc_textArea.fill = GridBagConstraints.BOTH;
gbc_textArea.gridx = 1;
gbc_textArea.gridy = 3;
JScrollPane scroll = new JScrollPane (textAreaDesription,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
contentPane.add(scroll, gbc_textArea);
JButton btnOk = new JButton("Ok");
GridBagConstraints gbc_btnOk = new GridBagConstraints();
gbc_btnOk.gridwidth = 2;
gbc_btnOk.gridx = 0;
gbc_btnOk.gridy = 4;
contentPane.add(btnOk, gbc_btnOk);
gvp = new GlassValidationPane();
FocusAdapter fl = new FocusAdapter() {
@Override
public void focusGained(FocusEvent fe) {
super.focusGained(fe);
((JTextComponent) fe.getSource()).setBorder(BorderFactory.createLineBorder(Color.gray));
}
public void focusLost(FocusEvent fe) {
super.focusLost(fe);
if(fe.getSource().equals(txtJobId)){
validationForInteger(txtJobId);
} else if(fe.getSource().equals(textAreaDesription)){
validationForText(textAreaDesription);
} else{
gvp.removeWarningIcon(((Component) fe.getSource()));
((JTextComponent) fe.getSource()).setBorder(BorderFactory.createLineBorder(Color.gray));
}
}
};
txtJobId.addFocusListener(fl);
textAreaDesription.addFocusListener(fl);
setGlassPane(gvp);
gvp.setVisible(true);
}
private void validationForInteger(JTextComponent comp){
String temp = comp.getText();
if(temp.matches("^[1-9]\\d*$")){
setGreen(comp);
} else {
setRed(comp);
}
}
private void validationForText(JTextComponent comp) {
System.out.println("In validation for text " + textAreaDesription.getY());
String temp = comp.getText();
if (temp.matches("^[a-zA-Z0-9][a-zA-Z0-9\\s_/-]+$")) {
setGreen(comp);
} else {
setRed(comp);
}
}
private void setRed(JTextComponent comp) {
comp.setBorder(BorderFactory.createLineBorder(Color.red));
gvp.showWarningIcon(comp);
}
private void setGreen(JTextComponent comp) {
comp.setBorder(BorderFactory.createLineBorder(Color.green));
gvp.removeWarningIcon(comp);
}
}
因此焦点侦听器将调用验证,并调用 classValidaionPane。如果它被调用,那么它会出错(但仅适用于 textArea 而不是 textField)有人可以帮我解决这个问题吗?