当FocusableWindowState为false时Swing Tooltip失效的合规解决方法
问题:无焦点悬浮Overlay中Swing Tooltip无法正常显示
我开发了一款针对全屏游戏的悬浮Overlay应用,给JFrame设置了以下属性:
this.setFocusableWindowState(false); this.setFocusable(false); this.setAlwaysOnTop(true);
但JFrame上按钮的Tooltip始终无法显示。查文档得知,JComponent.setTooltipText(String text)会向tooltipManager.sharedInstance注册组件,但仅当组件具备焦点绑定时才会生效(出自ToolTipManager.registerComponent方法文档)。
我试过把JFrame的setFocusableWindowState(true)改回来,但会导致窗口闪烁,没法稳定保持在游戏窗口上层。
目前我通过反射调用私有字段和方法实现了Tooltip显示(代码里的"tooltip magic"部分),但希望找到基于Swing内置函数的合规实现方式,不想用这种hack手段。之前也尝试过自行实现Tooltip系统,但引出了一堆其他问题。
以下是最小复现示例:
import javax.swing.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Main { public static void main(String args[]) { JFrame frame = new JFrame("Tooltip test"); frame.setVisible(true); frame.setFocusable(false); frame.setFocusableWindowState(false); frame.setAlwaysOnTop(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300,300); JButton button = new JButton("Press"); String tooltip = "tooltip value"; //notWorkingTooltip(button, tooltip); workingTooltip(button, tooltip); frame.getContentPane().add(button); } private static void notWorkingTooltip(JButton button, String tooltip) { button.setToolTipText(tooltip); } private static void workingTooltip(JButton button, String tooltip) { button.setToolTipText(tooltip); button.addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { UIManager.put("ToolTipManager.enableToolTipMode", "test"); try { Method method = ToolTipManager.class.getDeclaredMethod("showTipWindow"); Field field = ToolTipManager.class.getDeclaredField("mouseEvent"); field.setAccessible(true); field.set(ToolTipManager.sharedInstance(), e); method.setAccessible(true); method.invoke(ToolTipManager.sharedInstance()); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException ex) { ex.printStackTrace(); } ToolTipManager.sharedInstance().mouseMoved(e); ToolTipManager.sharedInstance().mouseEntered(e); } @Override public void mouseExited(MouseEvent e) { UIManager.put("ToolTipManager.enableToolTipMode", "activeApplication"); } }); } }
内容的提问来源于stack exchange,提问作者Morph21
相关产品推荐
相关产品推荐

