Pregunta

Estoy utilizando unos JFormattedTextFields en mi programa. Por alguna razón, cuando las ganancias de campo de texto se centran después de un clic en el campo de texto, la posición de intercalación siempre salta a la izquierda (posición 0). Me gustaría que el símbolo de intercalación para terminar en el lugar hecho clic el usuario. Así que si hago clic en medio de dos dígitos, el símbolo de intercalación debe terminar entre esos dos dígitos.

Así que implementó un FocusListener que obtener la ubicación clic y ajustar la posición de intercalación allí.

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

    });

He intentado varias cosas para conseguir su trabajar. He intentado usar la palabra clave final, que funciona, pero sólo para un único campo de texto.

conjunto

He usado / llegar métodos dentro del oyente enfoque para asignar el objeto actual, pero no estoy seguro de cómo hacer esto "seguro" (por ejemplo, qué necesitan estar sincronizados?).

Tal vez hay algo que me falta?

¿Fue útil?

Solución

Es necesario utilizar un 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);

Otros consejos

En realidad, esto sucede en AbstractFormatter.install(JFormattedTextField), que se llama cuando las ganancias de campo se centran.

No estoy seguro de por qué se ha diseñado de esta manera, pero se puede anular este comportamiento (siempre y cuando su formateador no cambia la longitud de la cadena en el campo.)

Ejemplo (asumiendo que el valor del campo es un 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());
    }
}

Tenga en cuenta que esto no es el mismo que el formateador Integer defecto. El formateador predeterminado utiliza un DecimalFormat que separa grupos de dígitos, por ejemplo, "1,000,000". Esto hace la tarea más difícil a medida que cambia la longitud de la cadena.

La mejora en la solución de finnw un poco creo. Ejemplo:

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top