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

Java 单击字段顶部时JTextField插入符号在开始位置的定位,java,swing,Java,Swing,当我单击JTextField的顶部时,插入符号将置于起始位置,而不管鼠标的x位置是什么。使用JPasswordField时不会发生这种情况 在这种特殊情况下,如何使JTextField像JPasswordField一样工作。 如果您想尝试,下面是代码: public static void main(String[] args) { JFrame frame = new JFrame(); JPanel panel = new JPanel(); panel.setLay

当我单击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。

据我所知,viewToModel。。。方法将用于确定插入符号位置。文本组件中给定元素的视图负责实现viewToModel。。。方法

BasicPasswordFieldUI使用:

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);
}
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);
}
如您所见,每个组件使用不同的视图

我想PasswordView是一个更容易实现的视图,因为所有字符都是相同的

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

我想您可以覆盖viewToModel。。。方法只使用MouseEvent的x值而忽略MouseEvent的y值。然后根据FontMetrics,您应该能够计算单击了哪个字符。

据我所知,viewToModel。。。方法将用于确定插入符号位置。文本组件中给定元素的视图负责实现viewToModel。。。方法

BasicPasswordFieldUI使用:

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);
}
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);
}
如您所见,每个组件使用不同的视图

我想PasswordView是一个更容易实现的视图,因为所有字符都是相同的

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


我想您可以覆盖viewToModel。。。方法只使用MouseEvent的x值而忽略MouseEvent的y值。然后,根据FontMetrics,您应该能够计算单击的字符。

您可以添加鼠标侦听器并手动设置选择:

        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设置为“char0”,例如不屏蔽文本,则选择行为与JTextField相同,很可能是因为camickr引用的视图的影响,您可以添加鼠标侦听器并手动设置选择:

        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设置为'char0',例如不屏蔽文本,则选择行为与JTextField完全相同,很可能是camickr引用的视图的影响

@copeg-I love it!我认为可以用tf.setCaretPositionloc替换setSelection开始和结束语句。我试图在不了解viewToModel的情况下解决这个问题。大约一年前,这将是一个很好的工具。1+请注意,如果您将JPasswordField的echo char设置为'char0',例如不屏蔽文本,则选择行为与JTextField相同-是的,当未设置屏蔽字符时,PasswordView中的代码将调用FieldView中的代码。这非常有效,不过,当您将鼠标拖动到顶部时,它仍会将插入符号移到起始位置。但至少这可以称为一种特征;通过从字段中删除mouseMotionListeners并添加我自己的来修复此问题。@copeg-我喜欢它!我认为可以用tf.setCaretPositionloc替换setSelection开始和结束语句。我试图在不了解viewToModel的情况下解决这个问题。大约一年前,这将是一个很好的工具。1+请注意,如果您将JPasswordField的echo char设置为'char0',例如不屏蔽文本,则选择行为与JTextField相同-是的,当未设置屏蔽字符时,PasswordView中的代码将调用FieldView中的代码。这非常有效,不过,当您将鼠标拖动到顶部时,它仍会将插入符号移到起始位置。但至少这可以称为一种特征;通过从字段中删除mouseMotionListeners并添加我自己的,修复了这个问题。这很好。我想我会坚持使用mouselistener,而不是深入挖掘来找出这种行为的原因。这很好。我想我会坚持使用mouselistener,而不是深入挖掘,找出这种行为的原因。