Java 如何在JTextArea中查找光标位置

Java 如何在JTextArea中查找光标位置,java,swing,jtextarea,Java,Swing,Jtextarea,有人能帮我在JTextArea中找到光标的像素位置吗? 我使用了txtArea.getCaretPosition()。但这不是我所期望的情况。实际上,我希望光标位置在像素的x,y坐标中。您可能需要使用FontMetrics类。 分析文本,找出文本的新行/换行。 然后使用 Font font = new Font("Verdana", Font.PLAIN, 10); FontMetrics metrics = new FontMetrics(font); Rectan

有人能帮我在JTextArea中找到光标的像素位置吗?
我使用了
txtArea.getCaretPosition()
。但这不是我所期望的情况。实际上,我希望光标位置在像素的
x,y
坐标中。

您可能需要使用FontMetrics类。
分析文本,找出文本的新行/换行。 然后使用

    Font font = new Font("Verdana", Font.PLAIN, 10);  
    FontMetrics metrics = new FontMetrics(font);
    Rectangle2D bounds = metrics.getStringBounds("string", null);  
    int widthInPixels = (int) bounds.getWidth();  
等等

如果您真的想,请将您的解决方案张贴在此处,让您觉得很酷。:)

使用方法
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();
            }
        });
    }
}
就像下面

Point point = textArea.getCaret().getMagicCaretPosition();

请注意,该点可能为空

我是在尝试了其他帖子后做出这一点的。只要您的textarea禁用了文字环绕功能,它就可以正常工作

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

比如,;使用此矩形显示弹出窗口:


显示(文本窗格,caretRect.x,caretRect.y)

请注意,其中一些答案返回相对于要从中获取插入符号位置的文本组件的位置

如果要在屏幕上获取插入符号的位置,我建议您使用以下方法:

Caret caret = yourTextComponent.getCaret();
Point p = caret.getMagicCaretPosition();
p.x += yourTextComponent.getLocationOnScreen().x;
p.y += yourTextComponent.getLocationOnScreen().y;

aFrameYourePositioning.setLocation(p);

下面是一个在插入符号位置显示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);

+1,您不需要为此使用UI。你可以使用textComponent.modelToView(…)。@camickr:Good point,我很惊讶我在滚动JTextComponent的API时错过了这一点,但在TextUI中发现它“更深”:我在想:在这种情况下,什么是“最佳实践”,根据你的评论更新我的答案,或者保留它以保存“历史”?好问题;两种常见做法包括:1)使用替代方法发布单独的答案,2)添加到相关
编辑
历史部分的链接。这一做法非常有效。在使用这些坐标显示JPOpupMenus时,使用任何其他方法都会遇到问题,但这一种方法非常完美。
Caret caret = yourTextComponent.getCaret();
Point p = caret.getMagicCaretPosition();
p.x += yourTextComponent.getLocationOnScreen().x;
p.y += yourTextComponent.getLocationOnScreen().y;

aFrameYourePositioning.setLocation(p);
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);