如何在 JTextArea 或 JTextPane 中显示多个插入符号

How to show multiple carets in a JTextArea or JTextPane

我想使用 JTextArea 或 JTextPane 作为代码更改播放器,代码更改和插入符移动记录在文本文件中。但问题是,它是由支持多选的编辑器记录的,所以一次有多个插入位置。

是否可以在 JTextArea 或 JTextPane 中显示多个插入符?

我尝试使用 JTextPane 并将代码呈现为 HTML,并在代码中插入了一些 <span class='caret'>|</span> 来表示插入符号,它有效但假插入符号需要 space,所以当插入符改变时,普通字符不会固定在屏幕上。

an editor which supports multi selection,

也许您应该使用 Highlighter 来突出显示文本选择的多个区域:

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;

public class TextAndNewLinesTest extends JFrame
{
    public TextAndNewLinesTest()
        throws Exception
    {
        String text =
            "one two three four five\r\n" +
            "one two three four five\r\n" +
            "one two three four five\r\n" +
            "one two three four five\r\n" +
            "one two three four five\r\n";

        JTextPane textPane = new JTextPane();
        textPane.setText(text);
        JScrollPane scrollPane = new JScrollPane( textPane );
        getContentPane().add( scrollPane );

        Highlighter.HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter( Color.cyan );

        String search = "three";
        int offset = 0;

        int length = textPane.getDocument().getLength();
        text = textPane.getDocument().getText(0, length);

        while ((offset = text.indexOf(search, offset)) != -1)
        {
            try
            {
                textPane.getHighlighter().addHighlight(offset, offset + 5, painter); // background
                offset += search.length();
            }
            catch(BadLocationException ble) {}
        }
    }

    public static void main(String[] args)
        throws Exception
    {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new TextAndNewLinesTest();
        frame.setTitle("Text and New Lines - Problem");
//      frame.setTitle("Text and New Lines - Fixed");
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.setSize(400, 120);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}

像这样?

import javax.swing.*;
import javax.swing.plaf.TextUI;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultCaret;
import java.awt.*;
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        JFrame fr=new JFrame("Multi caret test");
        JTextArea ta=new JTextArea("Test test test", 20, 40);
        MultiCaret c=new MultiCaret();
        c.setBlinkRate(500);
        c.setAdditionalDots(Arrays.asList(2,4,7));
        ta.setCaret(c);
        fr.add(ta);

        fr.pack();
        fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        fr.setLocationRelativeTo(null);
        fr.setVisible(true);
    }
}

class MultiCaret extends DefaultCaret {
    private List<Integer> additionalDots;

    public void setAdditionalDots(List<Integer> additionalDots) {
        this.additionalDots = additionalDots;
    }

    public void paint(Graphics g) {
        super.paint(g);

        try {
            TextUI mapper = getComponent().getUI();
            for (Integer addDot : additionalDots) {
                Rectangle r = mapper.modelToView(getComponent(), addDot, getDotBias());

                if(isVisible()) {
                    g.setColor(getComponent().getCaretColor());
                    int paintWidth = 1;
                    r.x -= paintWidth >> 1;
                    g.fillRect(r.x, r.y, paintWidth, r.height);
                }
                else {
                    getComponent().repaint(r);
                }
            }
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
    }

}