[英]JFormattedTextField caret position on focus
I am utilizing a few JFormattedTextFields in my program.我在我的程序中使用了一些 JFormattedTextFields。 For some reason when the text field gains focus after a click on the text field, the caret position always jumps to the left (position 0).出于某种原因,当单击文本字段后文本字段获得焦点时,插入符号位置总是向左跳(位置 0)。 I would like the caret to end up at the location clicked by the user.我希望插入符号最终出现在用户单击的位置。 So if I click in between two digits, the caret should end up in between those two digits.因此,如果我在两位数字之间单击,插入符号应位于这两位数字之间。
So I implemented a FocusListener that would get the click location and set the caret position there.所以我实现了一个 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) {}
});
I've tried a number of things to get his to work.我已经尝试了很多方法来让他工作。 I've tried using the final keyword, which works, but only for a single textfield.我试过使用 final 关键字,它有效,但仅适用于单个文本字段。
I've used set/get methods inside the focus listener to assign the current object, but am not sure about how to make this "safe" (eg do they need to be synchronized?).我在焦点侦听器中使用了 set/get 方法来分配当前对象,但不确定如何使这个“安全”(例如,它们是否需要同步?)。
Maybe there is something I am missing?也许我错过了什么?
You need to use a MouseListener:您需要使用 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);
This actually happens in AbstractFormatter.install(JFormattedTextField)
, which is called when the field gains focus.这实际上发生在AbstractFormatter.install(JFormattedTextField)
,当字段获得焦点时会调用它。
I'm not sure why it is designed this way, but you can override this behaviour (as long as your formatter does not change the length of the string in the field.)我不确定为什么它是这样设计的,但是您可以覆盖此行为(只要您的格式化程序不更改字段中字符串的长度。)
Example (assuming the field value is an int
):示例(假设字段值为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 that this is not the same as the default Integer
formatter.请注意,这与默认的Integer
格式化程序不同。 The default formatter uses a DecimalFormat
that separates groups of digits, eg "1,000,000"
.默认格式化程序使用DecimalFormat
来分隔数字组,例如"1,000,000"
。 This makes the task harder as it changes the length of the string.这使得任务更难,因为它改变了字符串的长度。
Improved on finnw's solution a bit I think.我认为改进了 finnw 的解决方案。 Example:例子:
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);
}
If you cannot or do not want to override the Formatter:如果您不能或不想覆盖格式化程序:
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.text.NumberFormat;
import javax.swing.JFormattedTextField;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.text.NumberFormatter;
public class TestJFormattedTextFieldFocus {
public static void main(String[] args) {
NumberFormat format = NumberFormat.getInstance();
NumberFormatter formatter = new NumberFormatter(format);
JFormattedTextField field = new JFormattedTextField(formatter);
field.addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent e) {
}
@Override
public void focusGained(FocusEvent e) {
restoreCaretPosition();
}
private void restoreCaretPosition() {
int caretPosition = field.getCaretPosition();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
field.setCaretPosition(caretPosition);
}
});
}
});
field.setValue(1234567890);
JOptionPane.showMessageDialog(null, field);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.