简体   繁体   English

JLabel ToolTip会干扰MouseListener

[英]JLabel ToolTip interferes with MouseListener

I have Java Swing application ToolTipMouseTest 我有Java Swing应用程序ToolTipMouseTest

The critical line is label.setToolTipText("label" + i); 关键行是label.setToolTipText("label" + i); . Once it is commented out very click on a label produces 2 mousePressed in console. 一旦注释掉,点击一个标签2 mousePressed在控制台中产生2 mousePressed With this line enabled click on labels would produce nothing. 启用此行后,单击标签将不会产生任何效果。

Is this expected behaviour or a bug? 这是预期的行为还是一个错误? My goal is to show tooltips without disabling MouseListener from working. 我的目标是显示工具提示而不禁用MouseListener

Almost SSCCE, but without imports: 几乎是SSCCE,但没有进口:

public class ToolTipMouseTest {

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            new ToolTipMouseTest();
        }
    });
}

public ToolTipMouseTest() {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new BorderLayout());

    JLayeredPane lpane = new JLayeredPane() {
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600,400);
        }
    };

    MouseAdapter1 mouseAdapter1 = new MouseAdapter1();
    lpane.addMouseListener(mouseAdapter1);

    frame.add(lpane);

    JPanel panel1 = new JPanel();
    panel1.setSize(new Dimension(600, 400));
    panel1.setOpaque(false);

    lpane.add(panel1, JLayeredPane.PALETTE_LAYER);

    JPanel panel2 = new JPanel();
    for (int i = 0; i < 5; i++) {
        JLabel label = new JLabel("Label " + i);
        panel2.add(label);
        label.setToolTipText("label" + i); //HERE!!
    }

    JScrollPane spane = new JScrollPane(panel2) {
        private static final long serialVersionUID = 1L;

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 200);
        }
    };

    MouseAdapter2 mouseAdapter2 = new MouseAdapter2();
    spane.addMouseListener(mouseAdapter2);

    panel1.add(spane);

    frame.pack();
    frame.setVisible(true);
}

private class MouseAdapter1 extends MouseAdapter {
    @Override
    public void mousePressed (MouseEvent me) {
        System.out.println("1 mousePressed");
    }
}

private class MouseAdapter2 extends MouseAdapter {
    @Override
    public void mousePressed (MouseEvent me) {
        System.out.println("2 mousePressed");
    }
}
}

It is working as intended. 它按预期工作。 Let me explain why. 让我解释一下原因。

When you are adding a tooltip to any component (labels in your case) they automatically recieve a new mouse listeners from ToolTipManager . 当您向任何组件(案例中的标签)添加工具提示时,它们会自动从ToolTipManager接收新的鼠标侦听器。 Here is the register method from ToolTipManager class: 这是ToolTipManager类的register方法:

public void registerComponent(JComponent component) {
    component.removeMouseListener(this);
    component.addMouseListener(this);
    component.removeMouseMotionListener(moveBeforeEnterListener);
    component.addMouseMotionListener(moveBeforeEnterListener);
    component.removeKeyListener(accessibilityKeyListener);
    component.addKeyListener(accessibilityKeyListener);
}

When any component has atleast one mouse listener set on it - it will block any mouse enter/exit/click/press/release events (mouse dragged/moved in case there is mouse motion listener set) from going down in the components hierarchy. 当任何组件上至少有一个鼠标监听器设置时 - 它将阻止任何鼠标进入/退出/单击/按下/释放事件(鼠标移动监听器设置时拖动/移动鼠标)从组件层次结构中向下移动。

In your case - labels blocking mouse events and mouse motion events from going down to layered pane due to ToolTipManager listeners installed when tooltip is set. 在您的情况下 - 由于在设置工具提示时安装了ToolTipManager侦听器,标签会阻止鼠标事件和鼠标移动事件下降到分层窗格。

This could be avoided if you make a workaround listener with that will pass events down. 如果您使用会将事件向下传递的变通方式侦听器,则可以避免这种情况。 For example you can add that listener to every component with a tooltip that should pass mouse events down. 例如,您可以使用应该传递鼠标事件的工具提示将该侦听器添加到每个组件。

Here is a small example of how that could be done: 这是一个如何做到的小例子:

label.addMouseListener ( new MouseAdapter ()
{
    public void mousePressed ( MouseEvent e )
    {
        lpane.dispatchEvent ( SwingUtilities.convertMouseEvent ( e.getComponent (), e, lpane ) );
    }
} );

In that case event will be passed to layered pane though. 在这种情况下,事件将传递到分层窗格。 Anyway you can dispatch this even anywhere you want (i guess it would be spane in your case). 无论如何,你甚至可以在任何你想要的地方发送这个(我想在你的情况下它会是spane )。

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

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