【问题标题】:Why Listeners are interdependent on one another in Java?为什么侦听器在 Java 中相互依赖?
【发布时间】:2013-03-30 13:05:59
【问题描述】:

我写了扫雷游戏。因为我有两个监听器作为一个按钮,

 class SampleClass extends MouseAdapter implements ActionListener  {

         //Some code here

          public void actionPerformed(ActionEvent event){ // Buttons listener..
               System.out.println("I came here to actionPerformed.");
               //Some Code
          }

         public void mouseClicked(MouseEvent event) { //Mouse listener..
               System.out.println("I came here to MouseClicked.");
              //Some Code
               if(event.getButton() == MouseEvent.BUTTON3){..}//If Right Mouse Button Is Clicked!!
               else if(event.getButton() == MouseEvent.BUTTON1){..}//If Left Mouse Button Is Clicked!!
         }
 }

我观察到的是,每当鼠标左键被点击时,唯一的actionPerformed 被调用而不是mouseClicked。但是在点击鼠标右键时,会调用mouseClicked(正常情况下不会调用actionPerformed)。

但是,当我删除 ActionListener 时,然后在 两次单击 左右鼠标按钮 mouseClicked 被调用 并且工作正常。

我以为,两个监听器是两个不同的独立线程,监听事件,但是为什么一个依赖另一个呢?

【问题讨论】:

  • 你指的是哪个框架?
  • @sanbhat JButton 。我没有得到框架这个词。

标签: java swing actionlistener mouselistener


【解决方案1】:

没有两个听众不相互依赖。 JButton 的属性是通过 space bar 或调用 doClick 或鼠标的 left click 来触发 Action。这就是为什么默认调用actionperformed 的原因(假设ActionListener 已注册)当您通过鼠标左键单击JButton 但在调用actionPerformed 之前调用mousePressed 事件。如果ActionListener 没有在JButton 中注册,MouseEvent 就会发挥作用并执行所需的操作。两个 Listener 彼此独立工作。事实上,动作是按正确的顺序触发的。例如JButton,如果 ActionListener 和 MouseListener 都已注册.. 那么触发的动作顺序如下:

  1. mousePressed()
  2. actionPerformed()
  3. mouseReleased()
  4. mouseClicked()

此代码将使您清楚这些要点。:

import javax.swing.*;
import java.awt.event.*;
import java.util.*;
class Listeners extends JFrame
{
    public void prepareAndShowGUI()
    {
        setTitle("Listeners dependency");
        JButton button = new JButton("Click");
        button.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent evt)
            {
                System.out.println("Action Listener has listened.");
            }
        });
        button.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent evt)
            {
                System.out.println("Mouse Clicked.");
            }
            public void mousePressed(MouseEvent evt)
            {
                System.out.println("Mouse pressed.");
            }
            public void mouseReleased(MouseEvent evt)
            {
                System.out.println("Mouse Released.");
            }
        });
        getContentPane().add(button);
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }
    public static void main(String stp[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                Listeners listen = new Listeners();
                listen.prepareAndShowGUI();
            }
        });
    }
}

点击JButton得到如下输出:

Mouse pressed.
Action Listener has listened.
Mouse Released.
Mouse Clicked.

【讨论】:

    【解决方案2】:

    AWT 的MouseListenerMouseMotionListener 处理有时会非常奇怪。 但是作为我认为的事件不应该相互干扰。

    如果组件没有鼠标监听器 然后鼠标事件被提升到父容器。这意味着你 可以不听父组件,仍然收到 所有子组件的事件。在上面的用例中,如果其他代码将鼠标侦听器添加到子组件,则鼠标事件不会冒泡到父容器。 这真是一个糟糕的设计。

    当且仅当我正在编写 JComponent 或 PL&F 的子类时,我更喜欢使用鼠标侦听器,因为它们可能会被其他事件侦听器覆盖。所以我想这就是你的情况。一个建议是使用 EventQueue 应该可以达到您的目的。

    【讨论】: