Java Swing:"permanent tooltip" 在 App 的 JFrame 上跟随鼠标光标的提示
Java Swing: "permanent tooltip" hint that follows mouse cursor on App's JFrame
我想创建一个类似工具提示(提示)的小工具 window,它将根据请求弹出,然后将鼠标光标放在应用程序 JFrame
上的任意位置,直到它稍后被销毁。它实际上是一条全局提示消息,要求用户执行特定任务(在许多不同的 windows 之间),一旦他们完成,它就会消失。例如:
GlobalToolTip panelHint = new GlobalToolTip("Global hint message.");
panelHint.show(); //Will remain visible and follow mouse
... //Waiting for user to perform a specific action or cancel
panelHint.hide(); //Hidden/destroyed here
我想创建自己的 class 从 JToolTip
/JPanel
扩展,或者如果可能的话覆盖默认的工具提示行为。也许使用应用程序 JFrame 的 JLayeredPane
或 glassPane?
我已经检查了一些其他解决方案,但都只适用于单个组件的行为。我也试过在 glassPane 上有一个 JPanel,但它没有被正确地绘制在其他一些 window 内容上。也许我没有在正确的地方调用它的绘制方法?
这似乎是一个很容易解决的问题,但我一直没能解决。任何帮助将不胜感激。
就个人而言,我不会为 glassPane 而烦恼,也不会为尝试让 JToolTip 或 ToolTipManager 做它们不应该做的事情而烦恼。我只想制作一个模仿 JToolTip 的 JLabel:
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.event.AWTEventListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class FollowTip {
private JWindow tip;
private final AWTEventListener mouseHandler = e -> {
Window window = tip.getOwner();
MouseEvent event = null;
switch (e.getID()) {
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
event = (MouseEvent) e;
if (window.isAncestorOf(event.getComponent())) {
Point loc = event.getLocationOnScreen();
tip.setLocation(loc.x + 10, loc.y + 10);
tip.setVisible(true);
}
break;
case MouseEvent.MOUSE_EXITED:
event = (MouseEvent) e;
Point p = SwingUtilities.convertPoint(
event.getComponent(), event.getPoint(), window);
if (!window.contains(p)) {
tip.setVisible(false);
}
break;
default:
break;
}
};
public FollowTip(String text,
Window window) {
JLabel tipLabel = new JLabel(text);
tipLabel.setForeground(UIManager.getColor("ToolTip.foreground"));
tipLabel.setBackground(UIManager.getColor("ToolTip.background"));
tipLabel.setFont(UIManager.getFont("ToolTip.font"));
tipLabel.setBorder(UIManager.getBorder("ToolTip.border"));
tip = new JWindow(window);
tip.setType(Window.Type.POPUP);
tip.setFocusableWindowState(false);
tip.getContentPane().add(tipLabel);
tip.pack();
}
public void activate() {
Window window = tip.getOwner();
window.getToolkit().addAWTEventListener(mouseHandler,
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
Point p = window.getMousePosition();
if (p != null) {
SwingUtilities.convertPointToScreen(p, window);
tip.setLocation(p.x + 10, p.y + 10);
tip.setVisible(true);
}
}
public void deactivate() {
Window window = tip.getOwner();
window.getToolkit().removeAWTEventListener(mouseHandler);
tip.setVisible(false);
}
static void showWindow() {
Object[][] data = new Object[12][];
Object[] headings = new Object[data.length];
for (int i = 0; i < data.length; i++) {
data[i] = new Object[data.length];
for (int j = 0; j < data[i].length; j++) {
data[i][j] = (i + 1) * (j + 1);
}
headings[i] = i;
}
JTable table = new JTable(data, headings);
JToggleButton button = new JToggleButton("Active");
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
JFrame frame = new JFrame("FollowTip");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(table));
frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
FollowTip tip = new FollowTip("This is a tip", frame);
button.addActionListener(e -> {
if (button.isSelected()) {
tip.activate();
} else {
tip.deactivate();
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> showWindow());
}
}
我想创建一个类似工具提示(提示)的小工具 window,它将根据请求弹出,然后将鼠标光标放在应用程序 JFrame
上的任意位置,直到它稍后被销毁。它实际上是一条全局提示消息,要求用户执行特定任务(在许多不同的 windows 之间),一旦他们完成,它就会消失。例如:
GlobalToolTip panelHint = new GlobalToolTip("Global hint message.");
panelHint.show(); //Will remain visible and follow mouse
... //Waiting for user to perform a specific action or cancel
panelHint.hide(); //Hidden/destroyed here
我想创建自己的 class 从 JToolTip
/JPanel
扩展,或者如果可能的话覆盖默认的工具提示行为。也许使用应用程序 JFrame 的 JLayeredPane
或 glassPane?
我已经检查了一些其他解决方案,但都只适用于单个组件的行为。我也试过在 glassPane 上有一个 JPanel,但它没有被正确地绘制在其他一些 window 内容上。也许我没有在正确的地方调用它的绘制方法?
这似乎是一个很容易解决的问题,但我一直没能解决。任何帮助将不胜感激。
就个人而言,我不会为 glassPane 而烦恼,也不会为尝试让 JToolTip 或 ToolTipManager 做它们不应该做的事情而烦恼。我只想制作一个模仿 JToolTip 的 JLabel:
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.event.AWTEventListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class FollowTip {
private JWindow tip;
private final AWTEventListener mouseHandler = e -> {
Window window = tip.getOwner();
MouseEvent event = null;
switch (e.getID()) {
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
event = (MouseEvent) e;
if (window.isAncestorOf(event.getComponent())) {
Point loc = event.getLocationOnScreen();
tip.setLocation(loc.x + 10, loc.y + 10);
tip.setVisible(true);
}
break;
case MouseEvent.MOUSE_EXITED:
event = (MouseEvent) e;
Point p = SwingUtilities.convertPoint(
event.getComponent(), event.getPoint(), window);
if (!window.contains(p)) {
tip.setVisible(false);
}
break;
default:
break;
}
};
public FollowTip(String text,
Window window) {
JLabel tipLabel = new JLabel(text);
tipLabel.setForeground(UIManager.getColor("ToolTip.foreground"));
tipLabel.setBackground(UIManager.getColor("ToolTip.background"));
tipLabel.setFont(UIManager.getFont("ToolTip.font"));
tipLabel.setBorder(UIManager.getBorder("ToolTip.border"));
tip = new JWindow(window);
tip.setType(Window.Type.POPUP);
tip.setFocusableWindowState(false);
tip.getContentPane().add(tipLabel);
tip.pack();
}
public void activate() {
Window window = tip.getOwner();
window.getToolkit().addAWTEventListener(mouseHandler,
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
Point p = window.getMousePosition();
if (p != null) {
SwingUtilities.convertPointToScreen(p, window);
tip.setLocation(p.x + 10, p.y + 10);
tip.setVisible(true);
}
}
public void deactivate() {
Window window = tip.getOwner();
window.getToolkit().removeAWTEventListener(mouseHandler);
tip.setVisible(false);
}
static void showWindow() {
Object[][] data = new Object[12][];
Object[] headings = new Object[data.length];
for (int i = 0; i < data.length; i++) {
data[i] = new Object[data.length];
for (int j = 0; j < data[i].length; j++) {
data[i][j] = (i + 1) * (j + 1);
}
headings[i] = i;
}
JTable table = new JTable(data, headings);
JToggleButton button = new JToggleButton("Active");
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
JFrame frame = new JFrame("FollowTip");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(table));
frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
FollowTip tip = new FollowTip("This is a tip", frame);
button.addActionListener(e -> {
if (button.isSelected()) {
tip.activate();
} else {
tip.deactivate();
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> showWindow());
}
}