Java 创建新行时看不到覆盖光标

Java 创建新行时看不到覆盖光标,java,swing,cursor,Java,Swing,Cursor,我正在尝试创建一个覆盖光标。我有它,但当我点击一个较早的行插入符号消失,然后当我点击一个新的行输入它再次出现 我应该在代码中更改什么来解决此问题 这是我的插入语课程: public class Mycaret extends DefaultCaret { protected static final int MIN_WIDTH = 8; protected DefaultCaret dc = null; JTextComponent com = null;

我正在尝试创建一个覆盖光标。我有它,但当我点击一个较早的行插入符号消失,然后当我点击一个新的行输入它再次出现

我应该在代码中更改什么来解决此问题

这是我的插入语课程:

public class Mycaret extends DefaultCaret {

    protected static final int MIN_WIDTH = 8;

    protected DefaultCaret dc = null;

    JTextComponent com = null;

    public Mycaret(int rate, DefaultCaret dc) {

        this.dc = dc;
        super.setBlinkRate(rate);
    }

    protected synchronized void damage(Rectangle r) {

        if (r != null) {

            try {

                JTextComponent comp = getComponent();
                TextUI mapper = comp.getUI();
                char dotChar = 0;
                if(comp.getText().length()>0){
                 dotChar = comp.getText().charAt(comp.getText().length()-1);
                }
                this.com = comp;

                Rectangle r2 = mapper.modelToView(comp, getDot() + 1);

                int width = r2.x - r.x;

                if (width == 0 ) {

                    width = MIN_WIDTH;


                }

                comp.repaint(r.x, r.y, width, r.height);

                this.x = r.x;
                this.y = r.y;
                this.width = width;
                this.height = r.height;

            }

            catch (BadLocationException e) {

            }
        }

    }

    public void paint(Graphics g) {

        char dotChar;

        if (isVisible()) {

            try {

                JTextComponent comp = getComponent();
                TextUI mapper = comp.getUI();

                Rectangle r1 = mapper.modelToView(comp, getDot());
                Rectangle r2 = mapper.modelToView(comp, getDot() + 1);

                g = g.create();
                g.setColor(comp.getForeground());
                g.setXORMode(comp.getBackground());

                int width = r2.x - r1.x;

                dotChar = comp.getText(getDot(), 1).charAt(0);

                if (width == 0  ) {
                    width = MIN_WIDTH;

                }



                g.fillRect(r1.x, r1.y, width, r1.height);
                g.dispose();

            } catch (BadLocationException e) {

            }
        }

    }
}
这是一个示例:

public class MyFrameSample extends JFrame {

    DefaultCaret caret=null;

    public MyFrameSample() {

        JTextArea text = new JTextArea(10,20);
        caret = new DefaultCaret();

        text.setCaret(new Mycaret(500, caret));
        add(text);

        pack();
        setVisible(true);
    }

    public static void main(String[] args) {

        new MyFrameSample();
    }
}

根据@user1803551观察,我注意到宽度可能为负数,所以我只是将if条件更改为“,正如我在评论中提到的,问题来自换行符(
\n
)。当插入符号放置在非空行中的
\n
之前时,它不会出现,因为它试图获取
\n
的宽度。因此,我添加了一个检查
\n
是否位于插入符号所在的同一位置

中写编辑:@camickr找到了一个更好的方法,发现
\n
的宽度是负数(任何人,为什么?请参阅评论)

说明:

isBeforeNewLine
方法从文档中获取插入符号位置处的文本。对于
JTextArea
而言,它是一个
纯文档
。如果它是
\n
,则宽度设置为
最小宽度
。必须对
绘制
损坏
方法都执行此操作。对n也很重要请注意,
\n
是独立于
JTextArea
系统的行分隔符,但其他文本组件的设置可能不同

注意事项:

  • 捕获异常时,至少可以打印堆栈跟踪
  • 我不认为有理由在
    paint
    中创建新的
    Graphics
    对象,请使用给定的对象
  • 适用时,使用
    @覆盖
  • 我只是需要做一些清理(重构),你可能想从中得到一些东西。我还更改了构造函数,因为你不需要向扩展它的类传递
    DefaultCaret

我已经编辑了我的问题是的,这应该是我的问题:)我想我在这方面有线索。我建议这是因为
modelToView(comp,getDot()+1)中存在陷阱
。请注意,胡萝卜仅在非空行(不是最后一行)的末尾停止渲染。这些位置正是文档中
\n
的位置。因为胡萝卜的宽度介于
getDot()
getDot()之间+1
,而
\n
是看不见的,你会得到一个看不见的胡萝卜。是的,这确实是换行符造成的。我很快会发布一些答案。
不知何故\n的宽度是负数(任何人,为什么?)
这是因为“\n”后面的下一个字符总是在下一行。(即getDot()+1,将从下一行获取字符)。该字符的“x”偏移量将始终为0。@camickr非常好!这解释了我最初观察到的粗体部分“仅在非空行的末尾,而非最后一行”。如果该行为空,则宽度将为0,否则为(负数)行中所有字符的宽度。很好的解释。Thanx是一个非常简单的解决方案!Thanx
if (width <= 0  ) 
{
    width = MIN_WIDTH;
}
public class Mycaret extends DefaultCaret {

    protected static final int MIN_WIDTH = 8;

    public Mycaret(int rate) {

        super.setBlinkRate(rate);
    }

    protected boolean isBeforeNewLine() throws BadLocationException {

        PlainDocument doc = (PlainDocument) getComponent().getDocument();
        if (doc.getText(getDot(), 1).equals("\n"))
            return true;
        return false;
    }

    @Override
    protected synchronized void damage(Rectangle r) {

        if (r != null) {
            try {
                JTextComponent comp = getComponent();

                Rectangle r2 = comp.getUI().modelToView(comp, getDot() + 1);
                int width = r2.x - r.x;
                if (width == 0 || isBeforeNewLine()) {
                    width = MIN_WIDTH;
                }
                comp.repaint(r.x, r.y, width, r.height);

                this.x = r.x;
                this.y = r.y;
                this.width = width;
                this.height = r.height;
            } catch (BadLocationException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void paint(Graphics g) {

        if (isVisible()) {
            try {
                JTextComponent comp = getComponent();

                g.setColor(comp.getForeground());
                g.setXORMode(comp.getBackground());

                Rectangle r1 = comp.getUI().modelToView(comp, getDot());
                Rectangle r2 = comp.getUI().modelToView(comp, getDot() + 1);
                int width = r2.x - r1.x;
                if (width == 0 || isBeforeNewLine()) {
                    width = MIN_WIDTH;
                }
                g.fillRect(r1.x, r1.y, width, r1.height);
            } catch (BadLocationException e) {
                e.printStackTrace();
            }
        }
    }
}