单击字段顶部时,JTextField插入符号在开始时定位

时间:2015-04-06 20:55:35

标签: java swing

当我点击JTextField的顶部时,无论鼠标的x位置是什么,都会将插入符号放在开头。使用JPasswordField时不会发生这种情况。

在这种特殊情况下,如何使JTextField像JPasswordField一样运行。 如果您想尝试,请输入以下代码:

public static void main(String[] args) {
    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(2, 1));
    panel.add(new JTextField("click here ^"));
    panel.add(new JPasswordField("click here ^"));
    frame.add(panel);
    frame.setSize(200, 200);
    frame.setVisible(true);
}

在这种情况下,JTextArea的行为类似于JPasswordField,但所有其他组件的行为都像JTextField。

2 个答案:

答案 0 :(得分:4)

您可以添加MouseListener并手动设置选择:

        final JTextField tf = new JTextField("click here ^");
        tf.addMouseListener(new MouseAdapter(){
            @Override
            public void mousePressed(MouseEvent e){
                try{
                    Rectangle rect = tf.modelToView(0);//for y value
                    System.out.println(tf.viewToModel(new Point(e.getX(), rect.y)));
                    int loc = tf.viewToModel(new Point(e.getX(), rect.y));
                    tf.setSelectionStart(loc);
                    tf.setSelectionEnd(loc);
                }catch(Exception ex){}//swallow the exception for demonstration only

            }
        });

作为旁注,请注意,如果将JPasswordField的echo char设置为'(char)0' (例如,没有掩盖文本),选择行为与JTextField相同(很可能是camickr引用的View的影响)

答案 1 :(得分:2)

据我了解,viewToModel(...)方法将用于确定插入位置。文本组件中给定View的{​​{1}}负责实施Element方法。

BasicPasswordFieldUI使用:

viewToModel(...)

BasicTextFieldUI使用:

public View create(Element elem) {
    return new PasswordView(elem);
}

因此,您可以看到每个组件使用不同的public View create(Element elem) { Document doc = elem.getDocument(); Object i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/); if (Boolean.TRUE.equals(i18nFlag)) { // To support bidirectional text, we build a more heavyweight // representation of the field. String kind = elem.getName(); if (kind != null) { if (kind.equals(AbstractDocument.ContentElementName)) { return new GlyphView(elem); } else if (kind.equals(AbstractDocument.ParagraphElementName)) { return new I18nFieldView(elem); } } // this shouldn't happen, should probably throw in this case. } return new FieldView(elem); }

我认为View是一个更简单的PasswordView来实现,因为所有字符都是相同的。

我不知道如何修改View以返回您想要的功能。

我想你可以覆盖FieldView viewToModel(...)方法,只使用x值并忽略MouseEvent的y值。然后基于FontMetrics,您应该能够计算出哪个字符被点击了。