7

プログラムでいくつかの JFormattedTextFields を利用しています。何らかの理由で、テキスト フィールドをクリックした後にテキスト フィールドがフォーカスされると、キャレットの位置が常に左 (位置 0) にジャンプします。ユーザーがクリックした場所にキャレットを配置したいと思います。したがって、2 つの数字の間をクリックすると、キャレットがその 2 つの数字の間に配置されるはずです。

そこで、クリック位置を取得してそこにキャレット位置を設定する 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 キーワードを使用してみましたが、これは機能しますが、単一のテキストフィールドに対してのみです。

フォーカス リスナー内で set/get メソッドを使用して現在のオブジェクトを割り当てましたが、これを "安全" にする方法がわかりません (たとえば、同期する必要がありますか?)。

多分私が見逃しているものがありますか?

4

4 に答える 4

12

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);
于 2010-02-04T18:10:46.600 に答える
7

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数字のグループを区切るa を使用します"1,000,000"。これにより、文字列の長さが変わるため、作業が難しくなります。

于 2010-02-04T18:14:51.853 に答える
1

私が思うに、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);
}
于 2013-07-03T07:18:44.123 に答える