سؤال

أنا أستخدم بعض JFormattEttextFields في برنامجي. لسبب ما عندما يركز حقل النصوص بعد نقرة على حقل النص، يقفز موضع Caret دائما إلى اليسار (الموضع 0). أرغب في نهاية المطاف في الموقع النقر فوق المستخدم. لذلك إذا قمت بالنقر فوق رقمين، يجب أن ينتهي الحيرة بين هذين الرقمين.

لذلك قمت بتنفيذ Focuslistener الذي سيحصل على موقع Click وضبط موضع Caret هناك.

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

    });

لقد جربت عددا من الأشياء للحصول على عمله. لقد حاولت استخدام الكلمة الرئيسية النهائية، والتي تعمل، ولكن فقط لنطاق Textfield واحد.

لقد استخدمت Set / Get طرق داخل المستمع التركيز لتعيين الكائن الحالي، لكنني لست متأكدا من كيفية جعل هذا "آمنا" (على سبيل المثال، يجب مزامنتها؟).

ربما هناك شيء أفتقده؟

هل كانت مفيدة؟

المحلول

تحتاج إلى استخدام 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);

نصائح أخرى

هذا يحدث في الواقع في 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". وبعد هذا يجعل المهمة أصعب كما يغير طول السلسلة.

تحسن على حل Finnw قليلا ما أعتقد. مثال:

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);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top