1

当输入与我期望的用户不同时,我有一个类在 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)有人可以帮我解决这个问题吗?

4

1 回答 1

2

JTextArea 的父组件与 JTextField 的父组件不同,因为 JTextArea 在 JScrollPane 内。我没有花时间阅读和理解您发布的所有代码,但您可能应该相对于 JScrollPane 的位置放置标签,而不是相对于 JTextArea 的位置。

于 2013-04-20T19:54:51.107 回答