简体   繁体   English

Java Swing:App 的 JFrame 上鼠标 cursor 后的“永久工具提示”提示

[英]Java Swing: "permanent tooltip" hint that follows mouse cursor on App's JFrame

I would like to create a small tooltip-like (hint) window that will popup upon request then follow the mouse cursor anywhere on the application's JFrame until it is later destroyed.我想创建一个类似工具提示(提示)的小提示(提示)window,它将根据请求弹出,然后在应用程序JFrame上的任何位置跟随鼠标 cursor,直到它被销毁。 It really is a global hint message asking the user to perform a specific task (between many different windows) and once they have done so, it will disappear.它实际上是一个全局提示消息,要求用户执行特定任务(在许多不同的窗口之间),一旦他们这样做了,它就会消失。 For example:例如:

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

I'm looking to either create my own class extending from JToolTip / JPanel or to override the default tooltip behavior if possible.我希望创建自己的 class 从JToolTip / JPanel扩展,或者如果可能的话覆盖默认的工具提示行为。 Perhaps using the app JFrame's JLayeredPane or glassPane?也许使用应用程序 JFrame 的JLayeredPane或 glassPane? I've checked a handful of other solutions but all apply to a single component's behavior only.我已经检查了一些其他解决方案,但都只适用于单个组件的行为。 I also tried having a JPanel on the glassPane but it wasn't being drawn properly over some of the other window contents.我也试过在 glassPane 上有一个 JPanel,但它没有被正确地绘制在其他一些 window 内容上。 Perhaps I was not calling its draw methods at the correct place?也许我没有在正确的地方调用它的绘图方法?

This seems like it should be a pretty easy problem to solve, but I have not been able to.这似乎应该是一个很容易解决的问题,但我一直没能解决。 Any help would be appreciated.任何帮助,将不胜感激。

Personally, I wouldn't bother with the glassPane and I wouldn't bother with trying to make a JToolTip or the ToolTipManager do things they weren't meant to do.就个人而言,我不会为 glassPane 而烦恼,也不会为尝试让 JToolTip 或 ToolTipManager 做它们不应该做的事情而烦恼。 I would just make a JLabel that mimics a JToolTip:我只想制作一个模仿 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());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM