【问题标题】:Where is the actionperfomed() method called?actionperfomed() 方法在哪里调用?
【发布时间】:2015-04-01 13:39:52
【问题描述】:

我是一名 Java 初学者,现在当我开始使用接口时,我想知道真正发生了什么。我想一个很好的例子是 ActionListener 接口。

我对接口的了解是,它迫使您实现接口提供的方法。但是我没有得到,调用 actionPerformed(ActionEvent e) 方法的地方。有没有什么简单的例子可以告诉我在后台发生了什么?还是谢谢。

【问题讨论】:

  • 看看thisOracle 教程。请留意actionPerformed 方法名称。
  • 问:Shane Voisard 的回答是否回答了您的问题?如果您查看他的堆栈回溯,您会看到 1) Java 运行时始终在寻找“事件”,2) 对于每个事件,它调用“java.awt.EventQueue.dispatchEvent()”,3) 最终调用您使用“addActionListener()”注册的代码(事件处理程序)。

标签: java interface


【解决方案1】:

如果您需要详细信息,请从ActionListener#actionPerformed 内部记录一个异常:

import java.io.*;
import javax.swing.*;
import java.awt.event.*;

public class ListenerTracer extends JPanel {

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() { createAndShowGUI(); }
        });
    }

    public ListenerTracer() {
        JButton b1 = new JButton("Press me");
        b1.setVerticalTextPosition(AbstractButton.CENTER);
        b1.setHorizontalTextPosition(AbstractButton.CENTER);
        b1.addActionListener(new ActionListener() {
            @Override public void actionPerformed(ActionEvent event) {
                Exception e = new Exception();
                e.printStackTrace();
            }
        });
        add(b1);

        JTextArea textArea = new JTextArea("actionListener printstacktrace:\n", 50, 50);
        JScrollPane scrollPane = new JScrollPane(textArea);
        add(scrollPane);
        Console.redirectOutput(textArea);
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("ListenerTracer");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ListenerTracer contentPane = new ListenerTracer();
        contentPane.setOpaque(true);
        frame.setContentPane(contentPane);
        frame.pack();
        frame.setVisible(true);
    }

    private static class Console implements Runnable {
        JTextArea displayPane;
        BufferedReader reader;

        private Console(JTextArea displayPane, PipedOutputStream pos) {
            this.displayPane = displayPane;
            try {
                PipedInputStream pis = new PipedInputStream(pos);
                reader = new BufferedReader( new InputStreamReader(pis) );
            }
            catch (IOException e) {}
        }

        public void run() {
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    displayPane.append( line + "\n" );
                    displayPane.setCaretPosition(displayPane.getDocument().getLength());
                }
                System.err.println("im here");
            }
            catch (IOException ioe) {
                JOptionPane.showMessageDialog(null, "Error redirecting output : "+ioe.getMessage());
            }
        }

        public static void redirectOutput(JTextArea displayPane) {
            PipedOutputStream pos = new PipedOutputStream();
            System.setErr(new PrintStream(pos, true) );
            Console console = new Console(displayPane, pos);
            new Thread(console).start();
        }
    }
}

单击“Press Me”按钮会产生以下输出:

actionListener printstacktrace: java.lang.Exception at ListenerTracer$2.actionPerformed(ListenerTracer.java:21) 在 javax.swing.AbstractButton.fireActionPerformed(未知来源)在 javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.fireActionPerformed(未知来源)在 javax.swing.DefaultButtonModel.setPressed(未知来源)在 javax.swing.plaf.basic.BasicButtonListener.mouseReleased(未知 源)在 java.awt.Component.processMouseEvent(未知源)在 javax.swing.JComponent.processMouseEvent(未知来源)在 java.awt.Component.processEvent(未知来源)在 java.awt.Container.processEvent(未知来源)在 java.awt.Component.dispatchEventImpl(未知来源)在 java.awt.Container.dispatchEventImpl(未知来源)在 java.awt.Component.dispatchEvent(未知来源)在 java.awt.LightweightDispatcher.retargetMouseEvent(未知来源)在 java.awt.LightweightDispatcher.processMouseEvent(未知来源)在 java.awt.LightweightDispatcher.dispatchEvent(未知来源)在 java.awt.Container.dispatchEventImpl(未知来源)在 java.awt.Window.dispatchEventImpl(未知来源)在 java.awt.Component.dispatchEvent(未知来源)在 java.awt.EventQueue.dispatchEventImpl(未知来源)在 java.awt.EventQueue.access$400(未知来源)在 java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知 来源)在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知 源)在 java.awt.EventQueue$4.run(未知源)在 java.awt.EventQueue$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知 源)在 java.awt.EventQueue.dispatchEvent(未知源)在 java.awt.EventDispatchThread.pumpOneEventForFilters(未知来源) 在 java.awt.EventDispatchThread.pumpEventsForFilter(未知来源) 在 java.awt.EventDispatchThread.pumpEventsForHierarchy(未知 来源)在 java.awt.EventDispatchThread.pumpEvents(未知来源) 在 java.awt.EventDispatchThread.pumpEvents(Unknown Source) 在 java.awt.EventDispatchThread.run(未知来源)

我从camickr's answer to redirecting-system-out-to-jtextpane借用了控制台重定向代码。

【讨论】:

    【解决方案2】:

    对于JButton,它的超类AbstractButton通过方法fireActionPerformed调用actionPerformed方法,这是一个受保护的方法。如果您查看源代码,您会发现它构造了一个ActionEvent 对象并使用它作为参数调用actionPerformed

    【讨论】:

      【解决方案3】:

      当用户做某事时会调用它。单击一个按钮,选择一个菜单。每个actionListeners 都被调用用于特定事件。我认为现在,您不必担心它被调用的确切位置、位置和原因。

      【讨论】:

      • 感谢您的回答。好吧,我知道它是在单击特定元素时调用的,我用 swing 制作了小 GUI,它们可以工作。但对我来说,很难理解调用 actionPerformed() 的特定代码在哪里。它在 JButton 类的某个地方吗?