JFormattedTextField acento circunflexo posição no foco
-
18-09-2019 - |
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?
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);
}