Java JFormattedTextField插入符号在焦点上的位置
我在程序中使用了一些JFormattedTextFields。出于某种原因,当文本字段在单击文本字段后获得焦点时,插入符号位置总是跳到左侧(位置0)。我希望插入符号结束于用户单击的位置。因此,如果我在两个数字之间单击,插入符号应该在这两个数字之间结束 因此,我实现了一个FocusListener,它将获取单击位置并在那里设置插入符号位置Java JFormattedTextField插入符号在焦点上的位置,java,swing,focus,caret,jformattedtextfield,Java,Swing,Focus,Caret,Jformattedtextfield,我在程序中使用了一些JFormattedTextFields。出于某种原因,当文本字段在单击文本字段后获得焦点时,插入符号位置总是跳到左侧(位置0)。我希望插入符号结束于用户单击的位置。因此,如果我在两个数字之间单击,插入符号应该在这两个数字之间结束 因此,我实现了一个FocusListener,它将获取单击位置并在那里设置插入符号位置 FocusListener focusListener = new FocusListener(){ public void focusGained
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关键字,这很有效,但只适用于单个文本字段
我在focus listener中使用了set/get方法来分配当前对象,但不确定如何使其“安全”(例如,它们是否需要同步?)
也许我遗漏了什么?你需要使用鼠标听筒:
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
):
请注意,这与默认的
Integer
格式化程序不同。默认格式设置程序使用分隔数字组的十进制格式,例如“1000000”
。这使得任务更加困难,因为它改变了字符串的长度。我认为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);
}
如果无法或不希望覆盖格式化程序:
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);
}
}
回答得好!但为什么需要在invokeLater()中执行此操作?mousePressed()不是从事件线程调用的吗?@Sanoj,invokeLater
引入的延迟是它工作所必需的。通常,单击字段时会获得焦点,这会导致格式化程序重新格式化值并更新字段文本。这样做的一个副作用是插入符号被移动。使用invokeLater
,此run()
方法在焦点事件处理完成之前不会执行,因此,您知道,一旦您将插入符号放在正确的位置,它就会留在那里。如果TableCellEditor中使用JFormattedTextField
,则此解决方案不起作用,但finnw的解决方案会起作用。@Jonas事实上,它起作用(假设您的评论与您最近的问题相关)-您必须重新发送转换的(到文本字段的坐标)MouseEvent或手动执行我答案中的//do stuff部分中的设置:-)@kleopatra:没有你的“hack”就不行,而finnw的解决方案在没有修改的情况下效果很好。
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);
}
}