简体   繁体   English

尝试将ActionListener添加到JButton

[英]Trying to add ActionListener to JButtons

I cannot figure out how to add Actionlisteners to the JButton s, any help would be much appreciated. 我不知道如何将Actionlisteners添加到JButton ,任何帮助将不胜感激。

public class Translator extends JPanel implements MouseListener, ActionListener {       

    private JButton french = new JButton();
    private JButton german = new JButton();
    private JButton irish = new JButton();

    public Translator(){
        french = new JButton("French");
        german = new JButton("German");
        irish = new JButton("Irish");           
        setLayout(new GridLayout(2,1));         
        buttonPanel.setLayout(new GridLayout(1,3));
        buttonPanel.add(french);
        buttonPanel.add(german);
        buttonPanel.add(irish);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub
    }
}

There are plenty of ways to add an ActionListener , to a given JComponent (that supports it's use). 有很多方法可以将ActionListener添加到给定的JComponent (支持它的使用)中。 I have added some comments in the code snippets, to help explain them a bit better, and some links in the comments for future reference. 我在代码段中添加了一些注释,以帮助更好地解释它们,并在注释中添加了一些链接,以供将来参考。

1.) If the class implements the ActionListener interface, ie the class itself contains the actionPerformed(...) method , then one can do it, in this manner: 1.) 如果该类实现了ActionListener接口,即该类本身包含actionPerformed(...)方法 ,则可以通过以下方式做到这一点:

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

public class Skeleton implements ActionListener {   

    private JFrame frame;
    private JPanel contentPane;
    private JButton button;

    private void displayGUI() {
        frame = new JFrame("Skeleton");
        /*
         * EXIT_ON_CLOSE is same as putting System.exit(0),
         * which in some sense, doesnot allows one's
         * application to terminate graciously.
         */ 
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new JPanel();
        button = new JButton("This is a button.");
        /*
         * This is one way of attaching an ActionListener
         * to the JButton, but the main disadvantage of
         * this approach is, it breaks encapsulation,
         * as you can see the public method, actionPerformed(),
         * is lying free to be accessed by any code outside
         * the scope of the class
         */
        button.addActionListener(this);

        contentPane.add(button);

        frame.setContentPane(contentPane);        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);                                
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new Skeleton().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JOptionPane.showMessageDialog(frame, "BINGO!",
            "Information: ", JOptionPane.INFORMATION_MESSAGE);
    }    
}

2.) If one doesn't wants to create unnecessary class files. 2) 如果不想创建不必要的class文件。 Then this approach, which uses, EventHandler can be used: 然后可以使用EventHandler这种方法:

import java.awt.*;
import java.awt.event.*;
import java.beans.EventHandler;
import javax.swing.*;

public class Example1 { 

    private JFrame frame;
    private JPanel contentPane;
    private JButton button;

    private void displayGUI() {
        frame = new JFrame("Skeleton");
        /*
         * EXIT_ON_CLOSE is same as putting System.exit(0),
         * which in some sense, doesnot allows one's
         * application to terminate graciously.
         */ 
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new JPanel();
        button = new JButton("This is a button.");
        /*
         * This is another way of attaching 
         * an ActionListener to the JButton,
         * the main advantage of this approach
         * is, that one does not have to create
         * a new class to handle events
         * More info regarding the use of this 
         * approach, can be found on this link : 
         * http://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html
         */
        button.addActionListener((ActionListener)
                EventHandler.create(ActionListener.class
                        , Example1.this, "buttonAction", ""));

        contentPane.add(button);

        frame.setContentPane(contentPane);        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);                                
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new Example1().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }

    public void buttonAction(ActionEvent e) {
        JOptionPane.showMessageDialog(frame, "BINGO!",
            "Information: ", JOptionPane.INFORMATION_MESSAGE);
    }    
}

3.) If one is more concern about the concept of Encapsulation , then this approach is beneficial: 3.) 如果人们更关心Encapsulation的概念,那么这种方法是有益的:

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

public class Example2 { 

    private JFrame frame;
    private JPanel contentPane;
    private JButton button;

    private ActionListener buttonActions = 
                            new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            JOptionPane.showMessageDialog(frame, "BINGO!",
                "Information: ", JOptionPane.INFORMATION_MESSAGE);
        }
    };

    private void displayGUI() {
        frame = new JFrame("Skeleton");
        /*
         * EXIT_ON_CLOSE is same as putting System.exit(0),
         * which in some sense, doesnot allows one's
         * application to terminate graciously.
         */ 
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new JPanel();
        button = new JButton("This is a button.");
        /*
         * This is another way of attaching 
         * an ActionListener to the JButton,
         * the main advantage of this approach
         * is, it adheres to encapsulation.
         */
        button.addActionListener(buttonActions);

        contentPane.add(button);

        frame.setContentPane(contentPane);        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);                                
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new Example2().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }    
}

4.) If one is more inclined towards creation of Anonymous Classes, then this approach can be used: 4.) 如果更倾向于创建匿名类,则可以使用这种方法:

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

public class Example3 { 

    private JFrame frame;
    private JPanel contentPane;
    private JButton button;

    private void displayGUI() {
        frame = new JFrame("Skeleton");
        /*
         * EXIT_ON_CLOSE is same as putting System.exit(0),
         * which in some sense, doesnot allows one's
         * application to terminate graciously.
         */ 
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new JPanel();
        button = new JButton("This is a button.");
        /* 
         * This is the fourth way of attaching  
         * an ActionListener to the JButton, 
         * the main advantage of this approach 
         * is, it adheres to encapsulation, the 
         * public method remains hidden
         * inside the Anonymous Class
         * More info can be found on this link : 
         * http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
         * The main disadvantage of this approach is
         * that it doesnot gives you the privilege
         * of separation of concerns, which can
         * be done using the fifth approach,
         * which is MVC - Pattern (Model-View-Controller)
         * and moreover, it creates a hell lot of classes, in 
         * your project, which can lead to extra overhead
         */
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                JOptionPane.showMessageDialog(frame, "BINGO!",
                    "Information: ", JOptionPane.INFORMATION_MESSAGE);
            }
        });

        contentPane.add(button);

        frame.setContentPane(contentPane);        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);                                
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new Example3().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }    
}

EDIT: 编辑:

5.) This approach, includes using Action instead of ActionListener . 5.) 这种方法包括使用Action而不是ActionListener This is to be used for sharing same functionality among various JComponent s, which leads to code reusability 这用于在各种JComponent之间共享相同的功能,从而导致代码可重用性

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

public class Example4 { 

    private JFrame frame;
    private JPanel contentPane;
    private JMenuItem showMenuItem;
    private JButton button;

    private Action myActions;

    /*
     * This approach is basically used, when
     * one wants to share the same functionality
     * of different JComponents among each other,
     * without writing redundant codes for each
     * one of those components. Here JMenuItem
     * and JButton are both using the same 
     * functionality, to perform the same task.
     * More info can be found on this link:
     * http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html
     */
    private class MyActions extends AbstractAction {
        public MyActions(String title, String desc) {
            super(title);
            putValue(SHORT_DESCRIPTION, desc);
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            JOptionPane.showMessageDialog(frame, "BINGO!",
                    "Information: ", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    private void displayGUI() {
        frame = new JFrame("Skeleton");
        /*
         * EXIT_ON_CLOSE is same as putting System.exit(0),
         * which in some sense, doesnot allows one's
         * application to terminate graciously.
         */ 
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new JPanel();
        button = new JButton("This is a button.");

        myActions = new MyActions("Show", "A small description");
        button.setAction(myActions);

        contentPane.add(button);

        frame.setJMenuBar(getJMenuBar());
        frame.setContentPane(contentPane);        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);                                
    }

    private JMenuBar getJMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        showMenuItem = new JMenuItem(myActions);
        fileMenu.add(showMenuItem);

        menuBar.add(fileMenu);

        return menuBar;
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new Example4().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }    
}
french.addActionListener(an_instance_of_the_class_where_actionPerformed_is);

which, as I can see after the edit, would be this 其中,因为我可以编辑看到后,会是this

Also, see this Example and some tutorial text in this corner of the web 另外,请参阅此示例和网络此角的一些教程文本

I think that the reference to the tutorial and the many examples is highly relevant. 我认为对本教程和许多示例的引用非常相关。

button.addActionListener(<your_ActionListener_here>);

In your case, it'll be: 在您的情况下,它将是:

french.addActionListener(this);

If you want to use the same ActionListener for all the three buttons, you can use the getSource() function of ActionEvent e to detect which button was actually pressed. 如果要对所有三个按钮使用相同的ActionListener,则可以使用ActionEvent e的getSource()函数来检测实际按下了哪个按钮。

If you are using Java8, you can try this. 如果您使用的是Java8,则可以尝试此操作。

JButton french = new JButton("French");
french.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent ae){
        System.out.println("Button french clicked!");
    }
});
french.addActionListener(button -> System.out.println("Button Click listener..."));
JFrame frame = new JFrame("Button Listener Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(french, BorderLayout.CENTER);
frame.setSize(250, 250);
frame.setVisible(true);

Obviously the answer is place this into your addActionListener method. 显然答案是将this放入您的addActionListener方法中。

The addActionListener method takes as an argument an object that implements ActionListener interface, this interface force you to implements/place-in-your-code the actionPerformed method which is the one that is called, when an action is triggered to the component that is assigned. addActionListener方法将实现 ActionListener接口的对象作为参数,当操作被触发给分配给组件的组件时,该接口将强制您实现/将您执行的代码放置在被执行的actionPerformed方法中。 。

So, placing this in your method, it will search inside the object you passed, in our case, the Translator object for an actionPerformed method and call it. 所以,把this在你的方法,将您传递的对象中进行搜索,在我们的情况下, Translator对象的actionPerformed方法并调用它。

this.french.addActionListener(this);

Of course there is a lot of code missing in order to work. 当然,为了工作,缺少很多代码。

I really liked @Sandeep answer take use of lambda expression. 我真的很喜欢@Sandeep答案使用lambda表达式。 You can see a full example below. 您可以在下面看到完整的示例。

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Translator extends JPanel implements ActionListener {       

    private JButton french = new JButton();
    private JButton german = new JButton();
    private JButton irish = new JButton();

    @SuppressWarnings("empty-statement")
    public Translator(){
        french = new JButton("French");
        german = new JButton("German");
        irish = new JButton("Irish");           
//        setLayout(new GridLayout(2,1));         
        this.setLayout(new GridLayout(1,3));
        this.add(french);
        this.add(german);
        this.add(irish);

        ActionListener ac = (ActionEvent ae) -> { System.out.println(((JButton) ae.getSource()).getText()); };
        this.french.addActionListener(ac);
        this.german.addActionListener(ac);
        this.irish.addActionListener(ac);
        this.irish.addActionListener(Translator.this);

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(((JButton) e.getSource()).getText());
    }

    public static void main(String[] args) {
        JFrame jframe = new JFrame("StackOverflow");
        jframe.add(new Translator());
        jframe.pack();
        jframe.setLocationRelativeTo(null);
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.setVisible(true);
    }
}
JButton button = new JButton("Button");
button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
        //To-Do
        //Button clicked
        });

Hope this helps, it's relatively simple! 希望这会有所帮助,这相对简单! You just need to add an ActionListener to your desired JButton 您只需要将ActionListener添加到所需的JButton中

To give you a broader idea of how to implement it in a case-scenario where I would like to run a new GUI frame after pressing a button: 为了让您更广泛地了解如何在需要按下按钮后运行新GUI框架的情况下实现它:

startNewFrame.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Starting new frame");
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    NewFrame newFrame = new NewFrame();
                    newFrame.setVisible(true);
                    dispose();//Disposes of current frame
                }
            });
        }
    });

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

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