Swing JTextArea上的文本 – 鼠标hoverpopup窗口?

有没有什么可以让你显示一个小的文本popup窗口(如工具提示)在Swing JTextArea 单个单词或字母? (或者具有类似function的JTextArea替代品。)

我需要的应该像一个工具提示,换句话说,只有当鼠标hover在单词上一两秒钟后才显示popup文本,一旦鼠标移开,它就会自动消失。 当然,这里棘手的部分是,我希望在文字中的字符/单词级别,而不是在组件级别…任何build议?

您可以根据需要重写getToolTipText(Mouse Event event)

附录: JTextComponentJTextArea的父类通过两种方法提供位置信息: modelToView()viewToModel() 。 后者应该让您将鼠标位置转换为文档偏移量。

也许

 import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.awt.geom.*; import javax.swing.*; import java.util.*; import javax.swing.event.*; public class SimplePaintSurface implements Runnable, ActionListener { private static final int WIDTH = 1250; private static final int HEIGHT = 800; private Random random = new Random(); private JFrame frame = new JFrame("SimplePaintSurface"); private JPanel tableaux; @Override public void run() { tableaux = new JPanel(null); for (int i = 1500; --i >= 0;) { addRandom(); } frame.add(tableaux, BorderLayout.CENTER); JButton add = new JButton("Add"); add.addActionListener(this); frame.add(add, BorderLayout.SOUTH); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(WIDTH, HEIGHT); frame.setLocationRelativeTo(null); frame.setVisible(true); tableaux.requestFocusInWindow(); } @Override public void actionPerformed(final ActionEvent e) { addRandom(); tableaux.repaint(); } void addRandom() { Letter letter = new Letter(Character.toString((char) ('a' + random.nextInt(26)))); letter.setBounds(random.nextInt(WIDTH), random.nextInt(HEIGHT), 16, 16); tableaux.add(letter); } public static void main(final String[] args) { SwingUtilities.invokeLater(new SimplePaintSurface()); } } class Letter extends JLabel { private Font font1; private Font font2; private final FontRenderContext fontRenderContext1; private final FontRenderContext fontRenderContext2; public Letter(final String letter) { super(letter); setFocusable(true); setBackground(Color.RED); font1 = getFont(); font2 = font1.deriveFont(48f); fontRenderContext1 = getFontMetrics(font1).getFontRenderContext(); fontRenderContext2 = getFontMetrics(font2).getFontRenderContext(); MouseInputAdapter mouseHandler = new MouseInputAdapter() { @Override public void mouseEntered(final MouseEvent e) { Letter.this.setOpaque(true); setFont(font2); Rectangle bounds = getBounds(); Rectangle2D stringBounds = font2.getStringBounds(getText(), fontRenderContext2); bounds.width = (int) stringBounds.getWidth(); bounds.height = (int) stringBounds.getHeight(); setBounds(bounds); } @Override public void mouseExited(final MouseEvent e) { Letter.this.setOpaque(false); setFont(font1); Rectangle bounds = getBounds(); Rectangle2D stringBounds = font1.getStringBounds(getText(), fontRenderContext1); bounds.width = (int) stringBounds.getWidth(); bounds.height = (int) stringBounds.getHeight(); setBounds(bounds); } }; addMouseListener(mouseHandler); } } 

当然,这里棘手的部分是我想要在文本中的字符/字级别

您可以使用鼠标点来确定您在文本区域中的位置:

 int offset = textArea.viewToModel(...); 

现在你有一个偏移量,你可以得到该位置的字符或单词。 Utilities类具有像getWordStart()和getWordEnd()这样的方法。

然后,使用getText(…)方法获取单词或字符。

这听起来很棘手。 这只是我的头顶,可能不会被投票。 但是你也许可以做到这一点。

假设有某种HoverListener或者你可以实现的东西,否则你将不得不实现一个鼠标监听器,并build立自己的等待计时器。 但是,一旦你到达这里,你知道你想要popup一个工具提示,你只是不知道他们在什么字母/单词。 我很确定,但是可以在屏幕上获得光标位置。 然后使用这个位置,你可以计算出光标在TextArea里面的位置,然后你可以抓住这个字符。 一旦你有了angular色/位置,你也可以抓住整个单词,而不需要太多的工作。 (注意,如果文本区域具有滚动条,则计算光标盘旋时文本区域的“视口”将仅显示屏幕上可见的区域)

对不起,罗嗦的答案,但这是我会尝试的一般逻辑,如果我有这个function,我知道Swing不提供它。 希望这是一个体面的起点。

这是一个基于@trashgods和@camickr的实际实现。

 addToolTip(line,toolTip) 

您可以添加一个工具提示,将鼠标hover在行上时显示的特定行。 您可能需要设置debug = true以获取每个位置的工具提示。

如果你想显示一个没有特定的行的通用工具提示,你可能想添加它

 addToolTip(-1,"general tool tip"). 

源代码:

 package com.bitplan.swingutil; import java.awt.event.MouseEvent; import java.util.HashMap; import java.util.Map; import javax.swing.JTextArea; import javax.swing.text.BadLocationException; /** * Answer for * http://stackoverflow.com/questions/5957241/text-mouseover-popups-over-a-swing-jtextarea/35250911#35250911 * * see http://stackoverflow.com/a/35250911/1497139 * a JTextArea that shows the current Position of the mouse as a tooltip * @author wf * */ public class JToolTipEventTextArea extends JTextArea { // make sure Eclipse doesn't show a warning private static final long serialVersionUID = 1L; // switch to display debugging tooltip boolean debug=false; /** * the map of tool tips per line */ public Map<Integer,String> lineToolTips=new HashMap<Integer,String>(); /** * create me with the given rows and columns * @param rows * @param cols */ public JToolTipEventTextArea(int rows, int cols) { super(rows,cols); // initialize the tool tip event handling this.setToolTipText(""); } /** * add a tool tip for the given line * @param line - the line number * @param tooltip - */ public void addToolTip(int line,String tooltip) { lineToolTips.put(line,tooltip); } /** * get the ToolTipText for the given mouse event * @param event - the mouse event to handle */ public String getToolTipText(MouseEvent event) { // convert the mouse position to a model position int viewToModel =viewToModel(event.getPoint()); // use -1 if we do not find a line number later int lineNo=-1; // debug information String line=" line ?"; // did we get a valid view to model position? if(viewToModel != -1){ try { // convert the modelPosition to a line number lineNo = this.getLineOfOffset(viewToModel)+1; // set the debug info line=" line "+lineNo; } catch (BadLocationException ble) { // in case the line number is invalid ignore this // in debug mode show the issue line=ble.getMessage(); } } // try to lookup the tool tip - will be null if the line number is invalid // if you want to show a general tool tip for invalid lines you might want to // add it with addToolTip(-1,"general tool tip") String toolTip=this.lineToolTips.get(lineNo); // if in debug mode show some info if (debug) { // different display whether we found a tooltip or not if (toolTip==null) { toolTip="no tooltip for line "+lineNo; } else { toolTip="tooltip: "+toolTip+" for line "+lineNo; } // generally we add the position info for debugging toolTip+=String.format(" at %3d / %3d ",event.getX(),event.getY()); } // now return the tool tip as wanted return toolTip; } }