I have a class that sets warning icons behind a textField when the input is different from what i expect form the user. For textfield this class works perfect, but when i'm trying to use it with a textArea the warning icons aren't set on the right location .
here is the class that sets and removes the warning icons:
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;
}
}
}
I have found that the getY() function for the textArea always gives 0 back, but i can't find why it always return 0. here is the code who calls the class 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);
}
}
thus the focus listners shall call for validation and there the classValidaionPane shall be called. If it is called then it goes wrong (but only for textArea's and not for textField) can somebody help me with this?
The parent component of the JTextArea is not the same as the parent component of the JTextField, since the JTextArea is inside a JScrollPane. I have not taken the time to read and understand all the code you posted, but you should probably placed the label relative to the position of the JScrollPane, and not relative to the position of the JTextArea.