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();
}
}
}
}