Pergunta

Eu estou utilizando algumas JFormattedTextFields no meu programa. Por alguma razão, quando os ganhos de campo de texto concentrar após um clique no campo de texto, a posição do cursor sempre salta para a esquerda (posição 0). Gostaria que o acento circunflexo para acabar no local clicado pelo usuário. Então, se eu clicar em entre dois dígitos, o acento circunflexo deve acabar entre esses dois dígitos.

Então eu implementado um focusListener que obter a localização clique e definir a posição do cursor lá.

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) {}

    });

Eu tentei uma série de coisas para obter o seu para trabalhar. Eu tentei usar a palavra-chave final, que funciona, mas apenas para um único campo de texto.

Eu usei set / get métodos dentro do ouvinte foco para atribuir o objeto atual, mas não estou certo sobre como fazer isso "seguro" (por exemplo, eles precisam ser sincronizados?).

Talvez haja algo que eu estou ausente?

Foi útil?

Solução

Você precisa usar um MouseListener:

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

Outras dicas

Isso realmente acontece em AbstractFormatter.install(JFormattedTextField), que é chamado quando os ganhos de campo foco.

Eu não sei por que ele foi concebido desta forma, mas você pode substituir esse comportamento (contanto que seu formatador não muda o comprimento da corda no campo.)

Exemplo (assumindo que o valor do campo é um 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());
    }
}

Note que este não é o mesmo que o formatador Integer padrão. O formatador padrão utiliza um DecimalFormat que separa os grupos de dígitos, por exemplo "1,000,000". Isto torna a tarefa mais difícil à medida que muda o comprimento da corda.

Melhoria na solução de finnw um pouco, eu acho. Exemplo:

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);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top