Java 如何使JTextComponent的插入符号跳过选定的文本?

Java 如何使JTextComponent的插入符号跳过选定的文本?,java,swing,selection,caret,jtextcomponent,Java,Swing,Selection,Caret,Jtextcomponent,许多环境中本机文本字段的正常行为如下: 带有文本“abcdefg”的文本字段。我用鼠标从左到右选择“efg”。插入符号现在位于“g”后面。当我通过按光标左键一次向左移动插入符号时,选择被删除,插入符号位于“e”之前。当我在JTextField或JTextArea(在Mac OS上测试)中执行相同的操作时,执行完全相同的操作会导致插入符号正好位于“g”之前 我知道如何通过使用KeyListener并将其注册到每个组件来以编程方式更改它,但我正在寻找一种方法来更改整个应用程序的设置。可能吗?有没有我

许多环境中本机文本字段的正常行为如下:

带有文本“abcdefg”的文本字段。我用鼠标从左到右选择“efg”。插入符号现在位于“g”后面。当我通过按光标左键一次向左移动插入符号时,选择被删除,插入符号位于“e”之前。当我在JTextField或JTextArea(在Mac OS上测试)中执行相同的操作时,执行完全相同的操作会导致插入符号正好位于“g”之前

我知道如何通过使用KeyListener并将其注册到每个组件来以编程方式更改它,但我正在寻找一种方法来更改整个应用程序的设置。可能吗?有没有我找不到的旗帜,或者我必须改变我的外观和感觉


谢谢

您所能做的是
addCaretListener

     anyField.addCaretListener(new CaretListener() {
        public void caretUpdate(CaretEvent evt) {
            anyFieldCaretUpdate(evt);
        }
       });
并再次将插入符号设置为最后一个:

  private void anyFieldCaretUpdate(CaretEvent evt) {

     anyField.setCaretPosition(anyField.getText().length());
        }
我正在寻找一种方法来改变我的整个应用程序


您还需要更改JTextArea、JFormattedTextField的ActionMap…

请告诉我们您为什么要这样做?为什么不使用backspace键删除所选文本?我只是想让用户从浏览器和其他本机应用程序中的文本字段中了解相同的行为。没有其他原因。在这个用例中,它不是关于删除文本,而是在其中移动,可能是在复制一个单词之后。我注意到,当我使用我们自己的应用程序时,我自己对它的这种行为感到惊讶,然后通过与其他应用程序进行比较,检查了为什么我会感到惊讶,并发现它们的行为不同,这就是“打破我的编辑流程”的原因。然而,我并不是要开始讨论如何编辑文本;-)。我刚刚发现了一个非常类似的问题:这是我所追求的行为,但我的问题是是否有办法集中启用它。@user1573546假设您不使用按键,而是使用鼠标从后到后高亮显示,在这种情况下,这个eg也可以工作,但不是链接:)@user1573546同样,在这种情况下,camickr的上述答案非常棒!太好了,谢谢!我现在唯一需要知道的是,把注册码放在哪里。ActionMap=(ActionMap)UIManager.get(“TextField.ActionMap”);在实例化第一个textfield之后,它可以可靠地工作,但在这之前,我需要在中心的某个位置执行它(或者使用调用新的JTextField()的变通方法,以确保action map属性已经存在)。到目前为止,当设置此属性时,我还无法找到可靠的信息(除了第一次使用JTextField之后)。我实际上打算发布一个关于该问题的问题。当我阅读
UIManger.get()
(或者是UIDefaults.get())时,似乎暗示第一次调用“get”如果使用惰性创建,则会创建对象。但这似乎对我也不起作用。因此,我的解决方案只是创建一个虚拟文本字段。是的,我在谷歌上搜索了有关UIManager生命周期的信息以找到答案,但没有找到任何有价值的信息。你会发布问题吗?如果不会,我可能会l、 谢谢我会让你发帖的,因为我现在不需要回答,只是好奇而已。好的,给你:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

public class CaretAction extends TextAction
{
    private boolean caretForward;

    public CaretAction(boolean caretForward)
    {
        super(caretForward ? "Caret Forward" : "Caret Backward");
        this.caretForward = caretForward;
    }

    public void actionPerformed(ActionEvent e)
    {
        JTextComponent textComponent = getFocusedComponent();

        int start = textComponent.getSelectionStart();
        int end = textComponent.getSelectionEnd();
        int offset = textComponent.getCaretPosition();

        if (start != end)
        {
            if (caretForward)
                offset = (offset == end) ? offset + 1 : end;
            else
                offset = (offset == start) ? offset -1 : start;
        }
        else
        {
            offset += (caretForward) ? 1 : -1;
        }

        offset = Math.max(offset, 0);
        offset = Math.min(offset, textComponent.getDocument().getLength());
        textComponent.setCaretPosition( offset );
    }

    private static void createAndShowUI()
    {
        JTextField textField1 = new JTextField(10);
        JTextField textField2 = new JTextField(10);

        JPanel panel = new JPanel();
        panel.add( textField1 );
        panel.add( textField2 );

        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( panel );
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );

        ActionMap map = (ActionMap)UIManager.get("TextField.actionMap");
        map.put(DefaultEditorKit.backwardAction, new CaretAction(false));
        map.put(DefaultEditorKit.forwardAction, new CaretAction(true));
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}