如何在JTextArea中查找光标位置

6

请问如何以像素为单位获取JTextArea中光标的位置? 我已经使用了txtArea.getCaretPosition(),但这不是我期望的位置。实际上我想要光标在像素坐标x,y中的位置。

7个回答

4

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

1
+1,你不需要使用用户界面来完成这个操作。你可以使用textComponent.modelToView(...)。 - camickr
@camickr:说得好,当我浏览JTextComponent的API时错过了这一点,但在TextUI中找到了更深入的内容:) 我在想:在这种情况下,“最佳实践”是什么,根据您的评论更新我的答案还是保留它以保留“历史记录”? - Uhlen
好问题;两种常见做法包括1)发布一个单独的答案,介绍另一种方法,2)添加一个链接到相关的“编辑”历史记录部分。 - trashgod

2
请注意,以下答案返回的位置是相对于文本组件中插入符号位置的位置。
如果您想获取插入符号在屏幕上的位置,建议使用以下方法:
Caret caret = yourTextComponent.getCaret();
Point p = caret.getMagicCaretPosition();
p.x += yourTextComponent.getLocationOnScreen().x;
p.y += yourTextComponent.getLocationOnScreen().y;

aFrameYourePositioning.setLocation(p);

这个方法非常有效。使用其他方法来显示JPopupMenu时遇到了问题,但是这个方法完美无缺。 - Alfabravo

0
Rectangle caretRect=textPane.getUI().modelToView(textPane,textPane.getCaretPosition());

或者

Rectangle caretRect=textPane.modelToView(textPane.getCaretPosition());

例如;使用此矩形来显示弹出菜单: popupMenu.show(textPane,caretRect.x,caretRect.y);

0

就像下面这样

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

请注意,该点可能为空。

0
你可能需要使用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();  

如果你真的想要,可以在这里发布你的解决方案,这样很酷。:)


0

在尝试了其他帖子后,我制作了这个。只要您的文本区域禁用了文本换行,它就可以完美地工作。

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

0

这里有一个示例,可以在插入符位置显示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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接