有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JFormattedTextField插入符号焦点位置

我在程序中使用了几个JFormattedTextFields。出于某种原因,当文本字段在单击文本字段后获得焦点时,插入符号位置总是跳到左侧(位置0)。我希望插入符号最终出现在用户单击的位置。所以如果我在两个数字之间点击,插入符号应该在这两个数字之间结束

所以我实现了一个FocusListener,它可以获取点击位置并在那里设置插入符号位置

FocusListener focusListener = new FocusListener(){


    public void focusGained(FocusEvent evt) {

        JFormettedTextField jftf = (JFormattedTextField) evt.getSource();

        //This is where the caret needs to be.
        int dot = jftf.getCaret().getDot(); 

        SwingUtilities.invokeLater( new Runnable() {

        public void run() {
'the textField that has focus'.setCaretPosition('Some how get the evt or dot');              
              }
           });
        }

    public void focusLost (FocusEvent evt) {}

    });

我试过很多方法让他工作。我尝试过使用final关键字,这很有效,但只适用于单个文本字段

我在focus listener中使用了set/get方法来分配当前对象,但不确定如何使其“安全”(例如,它们是否需要同步?)

也许我错过了什么


共 (4) 个答案

  1. # 1 楼答案

    这实际上发生在AbstractFormatter.install(JFormattedTextField)中,当字段获得焦点时调用它

    我不知道为什么它是这样设计的,但您可以重写这种行为(只要格式化程序不更改字段中字符串的长度)

    示例(假设字段值为int):

    class IntFormatter extends AbstractFormatter {
        @Override
        public void install(final JFormattedTextField ftf) {
            int prevLen = ftf.getDocument().getLength();
            int savedCaretPos = ftf.getCaretPosition();
            super.install(ftf);
            if (ftf.getDocument().getLength() == prevLen) {
                ftf.setCaretPosition(savedCaretPos);
            }
        }
    
        public Object stringToValue(String text) throws ParseException {
            return Integer.parseInt(text);
        }
    
        public String valueToString(Object value) throws ParseException {
            return Integer.toString(((Number) value).intValue());
        }
    }
    

    请注意,这与默认的Integer格式化程序不同。默认格式化程序使用DecimalFormat分隔数字组,例如"1,000,000"。这会使任务变得更加困难,因为它会更改字符串的长度

  2. # 2 楼答案

    如果不能或不想覆盖格式化程序:

        import java.awt.event.FocusEvent;
        import java.awt.event.FocusListener;
        import java.text.NumberFormat;
        
        import javax.swing.JFormattedTextField;
        import javax.swing.JOptionPane;
        import javax.swing.SwingUtilities;
        import javax.swing.text.NumberFormatter;
        
        public class TestJFormattedTextFieldFocus {
        
            public static void main(String[] args) {
                NumberFormat format = NumberFormat.getInstance();
                NumberFormatter formatter = new NumberFormatter(format);
                JFormattedTextField field = new JFormattedTextField(formatter);
                field.addFocusListener(new FocusListener() {
        
                    @Override
                    public void focusLost(FocusEvent e) {
                    }
        
                    @Override
                    public void focusGained(FocusEvent e) {
                        restoreCaretPosition();
                    }
        
                    private void restoreCaretPosition() {
                        int caretPosition = field.getCaretPosition();
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                field.setCaretPosition(caretPosition);
                            }
                        });
                    }
                });
                field.setValue(1234567890);
                JOptionPane.showMessageDialog(null, field);
            }
        
        }
    
  3. # 3 楼答案

    你需要使用鼠标听器:

    MouseListener ml = new MouseAdapter()
    {
        public void mousePressed(final MouseEvent e)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    JTextField tf = (JTextField)e.getSource();
                    int offset = tf.viewToModel(e.getPoint());
                    tf.setCaretPosition(offset);
                }
            });
        }
    };
    
    formattedTextField.addMouseListener(ml);
    
  4. # 4 楼答案

    我觉得芬恩的解决方案有点改进。例如:

    public static void main(String[] args) {
        NumberFormat format = NumberFormat.getInstance();
        NumberFormatter formatter = new NumberFormatter(format) {
            @Override
            public void install(JFormattedTextField pField) {
                final JFormattedTextField oldField = getFormattedTextField();
                final int oldLength = pField.getDocument().getLength();
                final int oldPosition = pField.getCaretPosition();
    
                super.install(pField);
    
                if (oldField == pField && oldLength == pField.getDocument().getLength()) {
                    pField.setCaretPosition(oldPosition);
                }
            }
        };
        JFormattedTextField field = new JFormattedTextField(formatter);
        field.setValue(1234567890);
    
        JOptionPane.showMessageDialog(null, field);
    }