java Swing JTextArea 上的文本鼠标悬停弹出窗口?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5957241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Text-mouseover popups over a Swing JTextArea?
提问by Manius
Is there anything out there that allows you to show a small text popup window (like a tooltip) over individual wordsor letters in a Swing JTextArea? (Or a JTextArea alternative with similar functionality.)
有没有什么东西可以让您在 Swing JTextArea 中的单个单词或字母上显示一个小的文本弹出窗口(如工具提示)?(或具有类似功能的 JTextArea 替代品。)
What I need should behave like a tooltip, in other words only display the popup text after the mouse has hovered over the word for a second or two, and it would vanish automatically once the mouse moves away. Of course the tricky part here is that I want it at the character/word level within the text, not at the component level... any suggestions?
我需要的应该表现得像一个工具提示,换句话说,只在鼠标悬停在单词上一两秒钟后显示弹出文本,一旦鼠标移开它就会自动消失。当然,这里棘手的部分是我希望它在文本中的字符/单词级别,而不是在组件级别......有什么建议吗?
回答by trashgod
You can override getToolTipText(Mouse Event event)
as needed.
您可以getToolTipText(Mouse Event event)
根据需要覆盖。
Addendum: JTextComponent
, the parent of JTextArea
provides location information via two methods: modelToView()
and viewToModel()
. The lattershould let you translate the mouse location into a document offset.
附录:JTextComponent
,的父级JTextArea
通过两种方法提供位置信息:modelToView()
和viewToModel()
。在后者应该让你翻译的鼠标位置插入到文档中的偏移。
回答by camickr
Of course the tricky part here is that I want it at the character/word level within the text
当然,这里棘手的部分是我希望它在文本中的字符/单词级别
You use the mouse point to determine where you are in the text area:
您可以使用鼠标点来确定您在文本区域中的位置:
int offset = textArea.viewToModel(...);
Now that you have an offset you can get the character or word at that location. The Utilities class has methods like getWordStart() and getWordEnd().
现在您有了一个偏移量,您可以在该位置获取字符或单词。Utilities 类具有 getWordStart() 和 getWordEnd() 等方法。
Then you use the getText(...) method to get the word or the character.
然后使用 getText(...) 方法获取单词或字符。
回答by mKorbel
maybe
或许
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);
}
}
回答by Wolfgang Fahl
Here is an actual implementation built on @trashgods and @camickr answer:
这是一个基于 @trashgods 和 @camickr 答案的实际实现:
with
和
addToolTip(line,toolTip)
you can add a tooltip for a specific line which will be displayed when you hover over the line. You might want to set debug=true to get a tooltip display for every location.
您可以为特定行添加工具提示,当您将鼠标悬停在该行上时将显示该提示。您可能希望设置 debug=true 以获取每个位置的工具提示显示。
if you want to show a general tool tip for lines that do not have specific one you might want to add it with
如果您想为没有特定行的行显示一般工具提示,您可能希望将其添加
addToolTip(-1,"general tool tip").
This solution is not 100% what was asked for but pretty close. With a few tweaks it should get the originally wanted result.
这个解决方案不是 100% 所要求的,但非常接近。通过一些调整,它应该得到最初想要的结果。
Source Code:
源代码:
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;
}
}
回答by gnomed
That sounds tricky. This is just off the top of my head and probably wont get voted. But you might be able to do this.
这听起来很棘手。这只是我的头顶,可能不会被投票。但你或许能够做到这一点。
Assuming there is some sort of HoverListener or something that you can implement, or else you will have to implement a mouse listener and build in your own wait timer. But once you get here, to a point where you know you want to popup a tooltip, you just dont know what letter/word they are on. I am pretty sure though that it is possible to get the cursor position on the screen. Then using this position you might be able to calculate where the cursor was inside the TextArea and then you can grab the character. Once you have the character/location you can also grab the whole word too without much more work. (NOTE that you want to get the "viewport" of the text area when calculating what the cursor was hovering over, if your text area has scroll bars the viewport will represent only the area visible on the screen)
假设有某种 HoverListener 或您可以实现的东西,否则您将不得不实现一个鼠标侦听器并构建您自己的等待计时器。但是一旦你到了这里,你知道你想要弹出一个工具提示,你只是不知道他们在哪个字母/单词上。我很确定虽然可以在屏幕上获得光标位置。然后使用这个位置,您可能能够计算出光标在 TextArea 内的位置,然后您就可以抓取该字符。一旦你有了角色/位置,你也可以不用做太多工作就可以抓取整个单词。(请注意,在计算光标悬停的内容时,您希望获得文本区域的“视口”,如果您的文本区域有滚动条,视口将仅代表屏幕上可见的区域)
Sorry for the very wordy answer, but that is the general logic I would try if I HAD to have this functionality and I know Swing does not offer it. Hopefully it makes a decent starting point.
抱歉我的回答非常冗长,但如果我必须拥有此功能并且我知道 Swing 不提供它,那么这是我会尝试的一般逻辑。希望它是一个不错的起点。