2013-04-20 5 views
1

У меня есть класс, который устанавливает значки предупреждений за текстовым полем, когда вход отличается от того, что я ожидаю от пользователя. Для текстового поля этот класс отлично работает, но когда я пытаюсь использовать его с textArea, значки предупреждений не устанавливаются в нужном месте.Значок не установлен прямо на GlassPane

здесь есть класс, который устанавливает и удаляет значки предупреждений:

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


} 

Я обнаружил, что функция GetY() для TEXTAREA всегда дает 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); 

    } 

} 

, таким образом, фокус listners наречет для проверки и там classValidaionPane наречется. Если он вызывается, тогда он идет не так (но только для textArea's, а не для textField) может кто-нибудь помочь мне с этим?

+0

нет, см. [Здесь] (http://stackoverflow.com/q/8715807/714968) и [здесь] (http://stackoverflow.com/a/9734016/714968), то же самое возможно с JViewport (видимый прямоугольник от JScrollPane) – mKorbel

ответ

2

Родительский компонент JTextArea не совпадает с родительским компонентом JTextField, так как JTextArea находится внутри JScrollPane. Я не нашел времени, чтобы прочитать и понять весь код, который вы опубликовали, но вы, вероятно, должны поместить метку относительно позиции JScrollPane, а не относительно позиции JTextArea.

+0

спасибо, теперь, когда вы говорите, что это на самом деле вполне логично – Bjorn

Смежные вопросы