java - 退出弹出窗口时防止调用 mouseExited

标签 java swing popup mouselistener

我正在尝试实现我自己的工具提示。我用Timer来做到这一点和鼠标监听器(对于 movedexited )。当鼠标移动时,计时器会重置,因此弹出窗口仅在鼠标静止时显示。当鼠标退出组件时,弹出窗口将隐藏。但是,当弹出窗口显示在光标处时,鼠标位于弹出窗口内,因此调用 mouseExited 。弹出窗口消失,但是,如果鼠标保持静止,它会再次发生,导致弹出窗口闪烁。可以通过将弹出窗口移动 1px 来防止这种情况,这样鼠标就不在弹出窗口中,但这并不能解决整个问题,因为将鼠标移到弹出窗口上会使它消失。

我的MCVE :

private static Timer timer = new Timer(100, new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        JPanel pop = new JPanel(new GridLayout(0, 3));
        pop.setBackground(Color.BLUE);
        // Do calculations similar to what would actually be happening,
        // because otherwise the flicker is too fast to demonstrate on my screen
        for (double i = Math.random() * 12; i < 40; i++) {
            BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB_PRE);
            Graphics2D g = img.createGraphics();
            g.drawString(Math.log(Math.sqrt(Math.random())) + "", 0, 32);
            g.dispose();

            pop.add(new JLabel(new ImageIcon(img)));
        }

        popup = PopupFactory.getSharedInstance().getPopup(panel, pop, x, y);
        popup.show();
    }
});
private static JPanel panel;
private static Popup popup;
private static int x, y;

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(640, 480);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    MouseAdapter ma = new MouseAdapter() {

        @Override
        public void mouseMoved(MouseEvent e) {
            timer.setRepeats(false);
            if (popup == null) timer.restart();
            x = e.getXOnScreen(); // Adding one here eliminates the flicker problem,
            y = e.getYOnScreen(); // but still calls mouseExited entering the popup
        }

        @Override
        public void mouseExited(MouseEvent e) {
            if (popup != null) {
                popup.hide();
                popup = null;
            }
            timer.stop();
        }

    };

    panel = new JPanel();
    panel.setBackground(Color.GREEN);
    panel.addMouseListener(ma);
    panel.addMouseMotionListener(ma);
    frame.add(panel);

    frame.setVisible(true);
}

我在想也许 mouseExited 方法应该检查弹出窗口的 mouseEntered 是否被调用,但我不知道如何做到这一点,它会当弹出窗口延伸到组件的边缘时也会引起问题。我希望鼠标监听器忽略弹出窗口。

如果弹出窗口随鼠标移动也可以,但我也不知道该怎么做。

最佳答案

However, when the popup is shown at the cursor, the mouse is inside the popup, so mouseExited is called.

您可以检查 MouseExited 事件坐标是否发生在 JPanel 的范围内。 ,并且只隐藏Popup如果事件发生在 JPanel 之外界限。

if ( panel.contains(e.getX(), e.getY() ) ){
    return;
}

考虑使用tool tips - 它为您处理事件并且高度可定制...多行可以通过 html 实现您可以通过 changing the look and feel 更改颜色

关于java - 退出弹出窗口时防止调用 mouseExited,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38637204/

相关文章:

java - 行添加两次 jtable

直到我将鼠标悬停在 Java 小程序按钮上才显示它们

javascript - 如何只显示一次点击弹窗

java - 不同表单action属性的区别

java - 哪一行代码使我的 RSS 阅读器只读取底部标签?

java - 保存(绘制)JPanel而不显示它

javascript - 我一直在尝试似乎没有让放大的弹出窗口正常工作

javascript - 打开时的放大弹出焦点按钮

java - 如何使用接口(interface)作为参数?

java - 在 Windows 10 中的命令行上使用 Java 开关