I would like to make it so that a user can select text that they've previously written into a textArea, then afterwards they would be able to select it and add a tooltip that would appear when hovering said text.
I tried to make it but i've only managed to have it show the tooltip when hovering anywhere inside of the textArea, meaning that whenever a tooltip is created, it will be shown if the mouse hovers inside of the textArea, irregardless of where it hovers, as opposed to having it only show the tooltip when the mouse hovers the string that it was created in.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;
public class toolTip extends JFrame {
private JTextArea textArea;
private JPopupMenu popupMenu;
private TooltipManager tooltipManager;
public toolTip() {
setTitle("Custom Tooltip Application");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textArea = new JTextArea();
tooltipManager = new TooltipManager(textArea);
popupMenu = new JPopupMenu();
JMenuItem addTooltipItem = new JMenuItem("Add Tooltip");
addTooltipItem.addActionListener(e -> addTooltip());
popupMenu.add(addTooltipItem);
textArea.setComponentPopupMenu(popupMenu);
add(new JScrollPane(textArea), BorderLayout.CENTER);
}
private void addTooltip() {
String selectedText = textArea.getSelectedText();
if (selectedText != null && !selectedText.isEmpty()) {
String tooltip = JOptionPane.showInputDialog("Enter tooltip text:");
if (tooltip != null && !tooltip.isEmpty()) {
tooltipManager.addTooltip(selectedText, tooltip);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new toolTip().setVisible(true));
}
}
class TooltipManager {
private JTextArea textArea;
private Map<String, String> tooltips = new HashMap<>();
public TooltipManager(JTextArea textArea) {
this.textArea = textArea;
textArea.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
updateTooltip(e);
}
});
}
public void addTooltip(String text, String tooltip) {
tooltips.put(text, tooltip);
}
private void updateTooltip(MouseEvent e) {
String word = getWordAtPoint(e.getPoint());
if (word != null && tooltips.containsKey(word)) {
textArea.setToolTipText(tooltips.get(word));
} else {
textArea.setToolTipText(null);
}
}
private String getWordAtPoint(Point p) {
int pos = textArea.viewToModel2D(p);
String text = textArea.getText();
int start = findWordStart(text, pos);
int end = findWordEnd(text, pos);
return text.substring(start, end);
}
private int findWordStart(String text, int pos) {
while (pos > 0 && Character.isLetterOrDigit(text.charAt(pos - 1))) {
pos--;
}
return pos;
}
private int findWordEnd(String text, int pos) {
while (pos < text.length() && Character.isLetterOrDigit(text.charAt(pos))) {
pos++;
}
return pos;
}
}
I would like to make it so that a user can select text that they've previously written into a textArea, then afterwards they would be able to select it and add a tooltip that would appear when hovering said text.
I tried to make it but i've only managed to have it show the tooltip when hovering anywhere inside of the textArea, meaning that whenever a tooltip is created, it will be shown if the mouse hovers inside of the textArea, irregardless of where it hovers, as opposed to having it only show the tooltip when the mouse hovers the string that it was created in.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;
public class toolTip extends JFrame {
private JTextArea textArea;
private JPopupMenu popupMenu;
private TooltipManager tooltipManager;
public toolTip() {
setTitle("Custom Tooltip Application");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textArea = new JTextArea();
tooltipManager = new TooltipManager(textArea);
popupMenu = new JPopupMenu();
JMenuItem addTooltipItem = new JMenuItem("Add Tooltip");
addTooltipItem.addActionListener(e -> addTooltip());
popupMenu.add(addTooltipItem);
textArea.setComponentPopupMenu(popupMenu);
add(new JScrollPane(textArea), BorderLayout.CENTER);
}
private void addTooltip() {
String selectedText = textArea.getSelectedText();
if (selectedText != null && !selectedText.isEmpty()) {
String tooltip = JOptionPane.showInputDialog("Enter tooltip text:");
if (tooltip != null && !tooltip.isEmpty()) {
tooltipManager.addTooltip(selectedText, tooltip);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new toolTip().setVisible(true));
}
}
class TooltipManager {
private JTextArea textArea;
private Map<String, String> tooltips = new HashMap<>();
public TooltipManager(JTextArea textArea) {
this.textArea = textArea;
textArea.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
updateTooltip(e);
}
});
}
public void addTooltip(String text, String tooltip) {
tooltips.put(text, tooltip);
}
private void updateTooltip(MouseEvent e) {
String word = getWordAtPoint(e.getPoint());
if (word != null && tooltips.containsKey(word)) {
textArea.setToolTipText(tooltips.get(word));
} else {
textArea.setToolTipText(null);
}
}
private String getWordAtPoint(Point p) {
int pos = textArea.viewToModel2D(p);
String text = textArea.getText();
int start = findWordStart(text, pos);
int end = findWordEnd(text, pos);
return text.substring(start, end);
}
private int findWordStart(String text, int pos) {
while (pos > 0 && Character.isLetterOrDigit(text.charAt(pos - 1))) {
pos--;
}
return pos;
}
private int findWordEnd(String text, int pos) {
while (pos < text.length() && Character.isLetterOrDigit(text.charAt(pos))) {
pos++;
}
return pos;
}
}
Share
Improve this question
edited Feb 5 at 12:47
Nicol64PA
asked Feb 5 at 5:03
Nicol64PANicol64PA
111 silver badge2 bronze badges
1 Answer
Reset to default 1I modified the GUI to make it easier for me to test.
The TooltipManager
class worked for me, but it took 2 or 3 seconds for the tooltip to display. When the mouse is moving, no tooltip displays. I'm running on Windows 10, using Java 22.
Here's the code I used. I made the TooltipManager
class an inner class.
import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TooltipExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TooltipExample());
}
private JTextArea textArea;
private TooltipManager tooltipManager;
@Override
public void run() {
JFrame frame = new JFrame("Custom Tooltip Application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTextPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createTextPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem addTooltipItem = new JMenuItem("Add Tooltip");
addTooltipItem.addActionListener(e -> addTooltip());
addTooltipItem.setFont(panel.getFont().deriveFont(20f));
popupMenu.add(addTooltipItem);
textArea = new JTextArea(10, 30);
textArea.setComponentPopupMenu(popupMenu);
textArea.setFont(panel.getFont().deriveFont(20f));
textArea.setText(createSampleText());
textArea.setCaretPosition(0);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
tooltipManager = new TooltipManager(textArea);
JScrollPane scrollPane = new JScrollPane(textArea);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private String createSampleText() {
return "I would like to make it so that a user can select "
+ "text that they've previously written into a "
+ "textArea, then afterwards they would be "
+ "able to select it and add a tooltip that "
+ "would appear when hovering said text.\r\n\r\n"
+ "I tried to make it but i've only managed"
+ " to have it show the tooltip when hovering"
+ " anywhere inside of the textArea, meaning"
+ " that whenever a tooltip is created, it "
+ "will be shown if the mouse hovers inside "
+ "of the textArea, irregardless of where it "
+ "hovers, as opposed to having it only show "
+ "the tooltip when the mouse hovers the "
+ "string that it was created in.";
}
private void addTooltip() {
String selectedText = textArea.getSelectedText();
// System.out.println(selectedText);
if (selectedText == null) {
JOptionPane.showMessageDialog(textArea,
"Please select a word for the tooltip.");
} else {
selectedText = selectedText.trim();
if (!selectedText.isEmpty()) {
String tooltipText = JOptionPane.showInputDialog(textArea,
"Enter tooltip text for \"" + selectedText + "\":");
tooltipManager.addTooltip(selectedText, tooltipText);
}
}
}
public class TooltipManager {
private JTextArea textArea;
private Map<String, String> tooltips;
public TooltipManager(JTextArea textArea) {
this.textArea = textArea;
this.tooltips = new HashMap<>();
textArea.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent event) {
// textArea.setToolTipText("Testing");
updateTooltip(event);
}
});
}
public void addTooltip(String text, String tooltip) {
tooltips.put(text, tooltip);
}
private void updateTooltip(MouseEvent event) {
String word = getWordAtPoint(event.getPoint());
// System.out.println(word);
if (word != null && tooltips.containsKey(word)) {
String text = tooltips.get(word);
textArea.setToolTipText(text);
// System.out.println("Success: " + text);
} else {
textArea.setToolTipText(null);
}
}
private String getWordAtPoint(Point p) {
int pos = textArea.viewToModel2D(p);
String text = textArea.getText();
int start = findWordStart(text, pos);
int end = findWordEnd(text, pos);
return text.substring(start, end);
}
private int findWordStart(String text, int pos) {
while (pos > 0 && Character.isLetterOrDigit(text.charAt(pos - 1))) {
pos--;
}
return pos;
}
private int findWordEnd(String text, int pos) {
while (pos < text.length()
&& Character.isLetterOrDigit(text.charAt(pos))) {
pos++;
}
return pos;
}
}
}