请问如何以像素为单位获取JTextArea中光标的位置?
我已经使用了txtArea.getCaretPosition()
,但这不是我期望的位置。实际上我想要光标在像素坐标x,y
中的位置。
TextUI有一个名为modelToView
的方法,可以提供光标位置/大小:
import java.awt.BorderLayout;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
public class PixelPositionOfCaretDemo
{
public PixelPositionOfCaretDemo()
{
JLabel label = new JLabel("Move the caret...");
JTextArea area = new JTextArea();
area.addCaretListener(new MyCaretListener(label));
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setBounds(new Rectangle(400, 400, 400, 400));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(area, BorderLayout.CENTER);
frame.add(label, BorderLayout.SOUTH);
frame.setVisible(true);
}
private static class MyCaretListener implements CaretListener
{
private final JLabel label;
MyCaretListener(JLabel label)
{
this.label = label;
}
@Override
public void caretUpdate(CaretEvent e)
{
JTextComponent textComp = (JTextComponent) e.getSource();
try
{
Rectangle rect = textComp.getUI().modelToView(textComp, e.getDot());
label.setText(rect.toString());
}
catch (BadLocationException ex)
{
throw new RuntimeException("Failed to get pixel position of caret", ex);
}
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new PixelPositionOfCaretDemo();
}
});
}
}
Caret caret = yourTextComponent.getCaret();
Point p = caret.getMagicCaretPosition();
p.x += yourTextComponent.getLocationOnScreen().x;
p.y += yourTextComponent.getLocationOnScreen().y;
aFrameYourePositioning.setLocation(p);
Rectangle caretRect=textPane.getUI().modelToView(textPane,textPane.getCaretPosition());
或者
Rectangle caretRect=textPane.modelToView(textPane.getCaretPosition());
就像下面这样
Point point = textArea.getCaret().getMagicCaretPosition();
Font font = new Font("Verdana", Font.PLAIN, 10);
FontMetrics metrics = new FontMetrics(font);
Rectangle2D bounds = metrics.getStringBounds("string", null);
int widthInPixels = (int) bounds.getWidth();
如果你真的想要,可以在这里发布你的解决方案,这样很酷。:)
在尝试了其他帖子后,我制作了这个。只要您的文本区域禁用了文本换行,它就可以完美地工作。
public Point getCaretPixelPosition(JTextArea a) {
try {
int cpos = a.getCaretPosition();
Font font = a.getStyledDocument().getFont(a.getStyledDocument().getLogicalStyle(cpos));
FontMetrics metrics = getFontMetrics(font);
int lineNum = a.getLineOfOffset(cpos);
int y = lineNum * metrics.getHeight();
int lineStart = a.getLineStartOffset(lineNum);
int x = metrics.stringWidth(a.getText().substring(lineStart, cpos));
return new Point(x,y);
} catch(BadLocationException e) {}
return null;
}
这里有一个示例,可以在插入符位置显示JPopup
Caret caret = logText.getCaret();
Point p = new Point(caret.getMagicCaretPosition());
p.x += logText.getLocationOnScreen().x;
p.y += logText.getLocationOnScreen().y;
SwingUtilities.convertPointFromScreen(p, actionsPanel);
popup.show(actionsPanel, p.x, p.y);